diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/dns_utils.cpp | 2 | ||||
-rw-r--r-- | src/common/util.cpp | 5 | ||||
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 2 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.cpp | 2 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_tx_utils.cpp | 5 | ||||
-rw-r--r-- | src/daemon/command_line_args.h | 6 | ||||
-rw-r--r-- | src/device/device.hpp | 36 | ||||
-rw-r--r-- | src/device/device_default.cpp | 26 | ||||
-rw-r--r-- | src/device/device_default.hpp | 12 | ||||
-rw-r--r-- | src/device/device_ledger.cpp | 689 | ||||
-rw-r--r-- | src/device/device_ledger.hpp | 46 | ||||
-rw-r--r-- | src/device/log.cpp | 10 | ||||
-rw-r--r-- | src/p2p/net_node.cpp | 2 | ||||
-rw-r--r-- | src/p2p/net_node.inl | 6 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 2 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.h | 2 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 45 | ||||
-rw-r--r-- | src/wallet/api/wallet.cpp | 2 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 167 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 5 |
20 files changed, 544 insertions, 528 deletions
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index 1ecdae8ec..33f60bc3c 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -230,7 +230,7 @@ DNSResolver::DNSResolver() : m_data(new DNSResolverData()) if (use_dns_public) { for (const auto &ip: dns_public_addr) - ub_ctx_set_fwd(m_data->m_ub_context, ip.c_str()); + ub_ctx_set_fwd(m_data->m_ub_context, string_copy(ip.c_str())); ub_ctx_set_option(m_data->m_ub_context, string_copy("do-udp:"), string_copy("no")); ub_ctx_set_option(m_data->m_ub_context, string_copy("do-tcp:"), string_copy("yes")); } diff --git a/src/common/util.cpp b/src/common/util.cpp index d01da0fb7..1877acb57 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -527,7 +527,10 @@ std::string get_nix_version_display_string() { ub_ctx *ctx = ub_ctx_create(); if (!ctx) return false; // cheat a bit, should not happen unless OOM - ub_ctx_zone_add(ctx, "monero", "unbound"); // this calls ub_ctx_finalize first, then errors out with UB_SYNTAX + char *monero = strdup("monero"), *unbound = strdup("unbound"); + ub_ctx_zone_add(ctx, monero, unbound); // this calls ub_ctx_finalize first, then errors out with UB_SYNTAX + free(unbound); + free(monero); // if no threads, bails out early with UB_NOERROR, otherwise fails with UB_AFTERFINAL id already finalized bool with_threads = ub_ctx_async(ctx, 1) != 0; // UB_AFTERFINAL is not defined in public headers, check any error ub_ctx_delete(ctx); diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 3db516847..f02a1f8d6 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -4365,7 +4365,7 @@ void Blockchain::cancel() } #if defined(PER_BLOCK_CHECKPOINT) -static const char expected_block_hashes_hash[] = "4b553162ee4e7af3c53666506591489c68560b9175e6e941dc96c89f96f0e35c"; +static const char expected_block_hashes_hash[] = "1d3df1a177bd6f752d87c0d7b960e502605742721afb39953265f1e0f7f9b01f"; void Blockchain::load_compiled_in_block_hashes() { const bool testnet = m_nettype == TESTNET; diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index e4a4cb2f1..4d852fc99 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -81,7 +81,7 @@ namespace cryptonote , "Specify data directory" , tools::get_default_data_dir() , {{ &arg_testnet_on, &arg_stagenet_on }} - , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string { if (testnet_stagenet[0]) return (boost::filesystem::path(val) / "testnet").string(); else if (testnet_stagenet[1]) diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index db4ab9e11..c2252fcc7 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -29,6 +29,7 @@ // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers #include <unordered_set> +#include <random> #include "include_base_utils.h" #include "string_tools.h" using namespace epee; @@ -316,7 +317,7 @@ namespace cryptonote // "Shuffle" outs std::vector<tx_destination_entry> shuffled_dsts(destinations); - std::random_shuffle(shuffled_dsts.begin(), shuffled_dsts.end(), [](unsigned int i) { return crypto::rand<unsigned int>() % i; }); + std::shuffle(shuffled_dsts.begin(), shuffled_dsts.end(), std::default_random_engine(crypto::rand<unsigned int>())); // sort ins by their key image std::vector<size_t> ins_order(sources.size()); @@ -363,7 +364,7 @@ namespace cryptonote uint64_t summary_outs_money = 0; //fill outputs size_t output_index = 0; - for(const tx_destination_entry& dst_entr: destinations) + for(const tx_destination_entry& dst_entr: shuffled_dsts) { CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount); crypto::key_derivation derivation; diff --git a/src/daemon/command_line_args.h b/src/daemon/command_line_args.h index add752029..4673590aa 100644 --- a/src/daemon/command_line_args.h +++ b/src/daemon/command_line_args.h @@ -42,7 +42,7 @@ namespace daemon_args , "Specify configuration file" , (daemonizer::get_default_data_dir() / std::string(CRYPTONOTE_NAME ".conf")).string() , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} - , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string { if (testnet_stagenet[0] && defaulted) return (daemonizer::get_default_data_dir() / "testnet" / std::string(CRYPTONOTE_NAME ".conf")).string(); @@ -57,7 +57,7 @@ namespace daemon_args , "Specify log file" , (daemonizer::get_default_data_dir() / std::string(CRYPTONOTE_NAME ".log")).string() , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} - , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string { if (testnet_stagenet[0] && defaulted) return (daemonizer::get_default_data_dir() / "testnet" / std::string(CRYPTONOTE_NAME ".log")).string(); @@ -102,7 +102,7 @@ namespace daemon_args , "Port for ZMQ RPC server to listen on" , std::to_string(config::ZMQ_RPC_DEFAULT_PORT) , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} - , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string { if (testnet_stagenet[0] && defaulted) return std::to_string(config::testnet::ZMQ_RPC_DEFAULT_PORT); if (testnet_stagenet[1] && defaulted) diff --git a/src/device/device.hpp b/src/device/device.hpp index b47460472..db489ff0c 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -80,6 +80,9 @@ namespace hw { class device { + protected: + std::string name; + public: device() {} @@ -87,12 +90,12 @@ namespace hw { virtual ~device() {} explicit virtual operator bool() const = 0; - - static const int SIGNATURE_REAL = 0; - static const int SIGNATURE_FAKE = 1; - - - std::string name; + enum device_mode { + NONE, + TRANSACTION_CREATE_REAL, + TRANSACTION_CREATE_FAKE, + TRANSACTION_PARSE + }; /* ======================================================================= */ /* SETUP/TEARDOWN */ @@ -104,7 +107,18 @@ namespace hw { virtual bool release() = 0; virtual bool connect(void) = 0; - virtual bool disconnect() = 0; + virtual bool disconnect(void) = 0; + + virtual bool set_mode(device_mode mode) = 0; + + + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + virtual void lock(void) = 0; + virtual void unlock(void) = 0; + virtual bool try_lock(void) = 0; + /* ======================================================================= */ /* WALLET & ADDRESS */ @@ -158,8 +172,6 @@ namespace hw { virtual bool open_tx(crypto::secret_key &tx_key) = 0; - virtual bool set_signature_mode(unsigned int sig_mode) = 0; - virtual bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) = 0; bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) { @@ -183,6 +195,12 @@ namespace hw { virtual bool close_tx(void) = 0; } ; + struct reset_mode { + device& hwref; + reset_mode(hw::device& dev) : hwref(dev) { } + ~reset_mode() { hwref.set_mode(hw::device::NONE);} + }; + device& get_device(const std::string device_descriptor) ; } diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index d63dafe9e..56bd1e164 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -31,6 +31,7 @@ #include "device_default.hpp" +#include "common/int-util.h" #include "cryptonote_basic/account.h" #include "cryptonote_basic/subaddress_index.h" #include "ringct/rctOps.h" @@ -81,6 +82,20 @@ namespace hw { dfns(); } + bool device_default::set_mode(device_mode mode) { + return true; + } + + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + + void device_default::lock() { } + + bool device_default::try_lock() { return true; } + + void device_default::unlock() { } + /* ======================================================================= */ /* WALLET & ADDRESS */ /* ======================================================================= */ @@ -181,10 +196,13 @@ namespace hw { crypto::secret_key device_default::get_subaddress_secret_key(const crypto::secret_key &a, const cryptonote::subaddress_index &index) { const char prefix[] = "SubAddr"; - char data[sizeof(prefix) + sizeof(crypto::secret_key) + sizeof(cryptonote::subaddress_index)]; + char data[sizeof(prefix) + sizeof(crypto::secret_key) + 2 * sizeof(uint32_t)]; memcpy(data, prefix, sizeof(prefix)); memcpy(data + sizeof(prefix), &a, sizeof(crypto::secret_key)); - memcpy(data + sizeof(prefix) + sizeof(crypto::secret_key), &index, sizeof(cryptonote::subaddress_index)); + uint32_t idx = SWAP32LE(index.major); + memcpy(data + sizeof(prefix) + sizeof(crypto::secret_key), &idx, sizeof(uint32_t)); + idx = SWAP32LE(index.minor); + memcpy(data + sizeof(prefix) + sizeof(crypto::secret_key) + sizeof(uint32_t), &idx, sizeof(uint32_t)); crypto::secret_key m; crypto::hash_to_scalar(data, sizeof(data), m); return m; @@ -262,10 +280,6 @@ namespace hw { return true; } - bool device_default::set_signature_mode(unsigned int sig_mode) { - return true; - } - bool device_default::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) { crypto::key_derivation derivation; crypto::hash hash; diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp index 02faeba0c..53942f53a 100644 --- a/src/device/device_default.hpp +++ b/src/device/device_default.hpp @@ -58,8 +58,17 @@ namespace hw { bool connect(void) override; bool disconnect() override; + + bool set_mode(device_mode mode) override; /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + void lock(void) override; + void unlock(void) override; + bool try_lock(void) override; + + /* ======================================================================= */ /* WALLET & ADDRESS */ /* ======================================================================= */ bool get_public_address(cryptonote::account_public_address &pubkey) override; @@ -97,9 +106,6 @@ namespace hw { bool open_tx(crypto::secret_key &tx_key) override; - //bool get_additional_key(const bool subaddr, cryptonote::keypair &additional_txkey) override; - bool set_signature_mode(unsigned int sig_mode) override; - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override; bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) override; diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index b3c0035a1..ee1497438 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -33,7 +33,8 @@ #include "cryptonote_basic/account.h" #include "cryptonote_basic/subaddress_index.h" - +#include <boost/thread/locks.hpp> +#include <boost/thread/lock_guard.hpp> namespace hw { @@ -57,8 +58,8 @@ namespace hw { #define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ; #ifdef DEBUG_HWDEVICE - crypto::secret_key viewkey; - crypto::secret_key spendkey; + crypto::secret_key dbg_viewkey; + crypto::secret_key dbg_spendkey; #endif /* ===================================================================== */ @@ -118,7 +119,14 @@ namespace hw { #endif /* ===================================================================== */ - /* === Device ==== */ + /* === Internal Helpers ==== */ + /* ===================================================================== */ + static bool is_fake_view_key(const crypto::secret_key &sec) { + return sec == crypto::null_skey; + } + + /* ===================================================================== */ + /* === Device ==== */ /* ===================================================================== */ static int device_id = 0; @@ -196,6 +204,8 @@ namespace hw { this->hCard = 0; this->hContext = 0; this->reset_buffer(); + this->mode = NONE; + this->has_view_key = false; MDEBUG( "Device "<<this->id <<" Created"); } @@ -204,14 +214,51 @@ namespace hw { MDEBUG( "Device "<<this->id <<" Destroyed"); } + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + + //automatic lock one more level on device ensuring the current thread is allowed to use it + #define AUTO_LOCK_CMD() \ + /* lock both mutexes without deadlock*/ \ + boost::lock(device_locker, command_locker); \ + /* make sure both already-locked mutexes are unlocked at the end of scope */ \ + boost::lock_guard<boost::recursive_mutex> lock1(device_locker, boost::adopt_lock); \ + boost::lock_guard<boost::mutex> lock2(command_locker, boost::adopt_lock) + + //lock the device for a long sequence + void device_ledger::lock(void) { + MDEBUG( "Ask for LOCKING for device "<<this->name << " in thread "); + device_locker.lock(); + MDEBUG( "Device "<<this->name << " LOCKed"); + } + + //lock the device for a long sequence + bool device_ledger::try_lock(void) { + MDEBUG( "Ask for LOCKING(try) for device "<<this->name << " in thread "); + bool r = device_locker.try_lock(); + if (r) { + MDEBUG( "Device "<<this->name << " LOCKed(try)"); + } else { + MDEBUG( "Device "<<this->name << " not LOCKed(try)"); + } + return r; + } + + //lock the device for a long sequence + void device_ledger::unlock(void) { + try { + MDEBUG( "Ask for UNLOCKING for device "<<this->name << " in thread "); + } catch (...) { + } + device_locker.unlock(); + MDEBUG( "Device "<<this->name << " UNLOCKed"); + } /* ======================================================================= */ /* MISC */ /* ======================================================================= */ bool device_ledger::reset() { - - lock_device(); - try { int offset; reset_buffer(); @@ -227,12 +274,7 @@ namespace hw { this->buffer_send[4] = offset-5; this->length_send = offset; this->exchange(); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) { @@ -261,30 +303,6 @@ namespace hw { memset(this->buffer_recv, 0, BUFFER_RECV_SIZE); } - void device_ledger::lock_device() { - MDEBUG( "Ask for LOCKING for device "<<this->id); - device_locker.lock(); - MDEBUG( "Device "<<this->id << " LOCKed"); - } - void device_ledger::unlock_device() { - try { - MDEBUG( "Ask for UNLOCKING for device "<<this->id); - } catch (...) { - } - device_locker.unlock(); - MDEBUG( "Device "<<this->id << " UNLOCKed"); - } - void device_ledger::lock_tx() { - MDEBUG( "Ask for LOCKING for TX "<<this->id); - //tx_locker.lock(); - MDEBUG( "TX "<<this->id << " LOCKed"); - } - void device_ledger::unlock_tx() { - MDEBUG( "Ask for UNLOCKING for TX "<<this->id); - //tx_locker.unlock(); - MDEBUG( "TX "<<this->id << " UNLOCKed"); - } - /* ======================================================================= */ /* SETUP/TEARDOWN */ /* ======================================================================= */ @@ -394,10 +412,10 @@ namespace hw { #ifdef DEBUG_HWDEVICE cryptonote::account_public_address pubkey; this->get_public_address(pubkey); + #endif crypto::secret_key vkey; crypto::secret_key skey; this->get_secret_keys(vkey,skey); - #endif return rv==SCARD_S_SUCCESS; } @@ -411,16 +429,55 @@ namespace hw { return true; } + bool device_ledger::set_mode(device_mode mode) { + AUTO_LOCK_CMD(); + + int offset; + + reset_buffer(); + + switch(mode) { + case TRANSACTION_CREATE_REAL: + case TRANSACTION_CREATE_FAKE: + this->buffer_send[0] = 0x00; + this->buffer_send[1] = INS_SET_SIGNATURE_MODE; + this->buffer_send[2] = 0x01; + this->buffer_send[3] = 0x00; + this->buffer_send[4] = 0x00; + offset = 5; + //options + this->buffer_send[offset] = 0x00; + offset += 1; + //account + this->buffer_send[offset] = mode; + offset += 1; + + this->buffer_send[4] = offset-5; + this->length_send = offset; + this->exchange(); + + this->mode = mode; + break; + + case TRANSACTION_PARSE: + case NONE: + this->mode = mode; + break; + default: + CHECK_AND_ASSERT_THROW_MES(false, " device_ledger::set_mode(unsigned int mode): invalid mode: "<<mode); + } + MDEBUG("Switch to mode: " <<mode); + return true; + } + /* ======================================================================= */ /* WALLET & ADDRESS */ /* ======================================================================= */ - /* Application API */ bool device_ledger::get_public_address(cryptonote::account_public_address &pubkey){ + AUTO_LOCK_CMD(); - lock_device(); - try { int offset; reset_buffer(); @@ -440,21 +497,17 @@ namespace hw { memmove(pubkey.m_view_public_key.data, this->buffer_recv, 32); memmove(pubkey.m_spend_public_key.data, this->buffer_recv+32, 32); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + + return true; } - bool device_ledger::get_secret_keys(crypto::secret_key &viewkey , crypto::secret_key &spendkey) { - memset(viewkey.data, 0x00, 32); - memset(spendkey.data, 0xFF, 32); + bool device_ledger::get_secret_keys(crypto::secret_key &vkey , crypto::secret_key &skey) { + AUTO_LOCK_CMD(); + + //secret key are represented as fake key on the wallet side + memset(vkey.data, 0x00, 32); + memset(skey.data, 0xFF, 32); - #ifdef DEBUG_HWDEVICE - lock_device(); - try { //spcialkey, normal conf handled in decrypt int offset; reset_buffer(); @@ -473,21 +526,26 @@ namespace hw { this->length_send = offset; this->exchange(); - //clear key - memmove(ledger::viewkey.data, this->buffer_recv+64, 32); - memmove(ledger::spendkey.data, this->buffer_recv+96, 32); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - #endif - return true; + //View key is retrievied, if allowed, to speed up blockchain parsing + memmove(this->viewkey.data, this->buffer_recv+0, 32); + if (is_fake_view_key(this->viewkey)) { + MDEBUG("Have Not view key"); + this->has_view_key = false; + } else { + MDEBUG("Have view key"); + this->has_view_key = true; + } + + #ifdef DEBUG_HWDEVICE + memmove(dbg_viewkey.data, this->buffer_recv+0, 32); + memmove(dbg_spendkey.data, this->buffer_recv+32, 32); + #endif + + return true; } bool device_ledger::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key) { - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; #ifdef DEBUG_HWDEVICE @@ -519,11 +577,6 @@ namespace hw { hw::ledger::check32("generate_chacha_key_prehashed", "key", (char*)key_x.data(), (char*)key.data()); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } return true; } @@ -532,15 +585,15 @@ namespace hw { /* ======================================================================= */ bool device_ledger::derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub){ - - lock_device(); - try { - int offset =0; - unsigned char options = 0; - + AUTO_LOCK_CMD(); #ifdef DEBUG_HWDEVICE const crypto::public_key pub_x = pub; - const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); + crypto::key_derivation derivation_x; + if ((this->mode == TRANSACTION_PARSE) && has_view_key) { + derivation_x = derivation; + } else { + derivation_x = hw::ledger::decrypt(derivation); + } const std::size_t output_index_x = output_index; crypto::public_key derived_pub_x; hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub_x.data, 32); @@ -550,10 +603,17 @@ namespace hw { hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32); #endif + if ((this->mode == TRANSACTION_PARSE) && has_view_key) { + //If we are in TRANSACTION_PARSE, the given derivation has been retrieved uncrypted (wihtout the help + //of the device), so continue that way. + MDEBUG( "derive_subaddress_public_key : PARSE mode with known viewkey"); + crypto::derive_subaddress_public_key(pub, derivation, output_index,derived_pub); + } else { + + int offset =0; + reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_DERIVE_SUBADDRESS_PUBLIC_KEY; this->buffer_send[2] = 0x00; @@ -561,7 +621,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //pub memmove(this->buffer_send+offset, pub.data, 32); @@ -582,34 +642,27 @@ namespace hw { //pub key memmove(derived_pub.data, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); - #endif - - unlock_device(); - }catch (...) { - unlock_device(); - throw; } + #ifdef DEBUG_HWDEVICE + hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); + #endif + return true; } crypto::public_key device_ledger::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { - crypto::public_key D; - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + crypto::public_key D; + int offset; #ifdef DEBUG_HWDEVICE const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); const cryptonote::subaddress_index index_x = index; crypto::public_key D_x; - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data,32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_spend_secret_key", keys_x.m_spend_secret_key.data,32); + hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data,32); + hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_spend_secret_key", keys_x.m_spend_secret_key.data,32); hw::ledger::log_message ("get_subaddress_spend_public_key: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor)); - this->controle_device->get_subaddress_spend_public_key(keys_x, index_x, D_x); + D_x = this->controle_device->get_subaddress_spend_public_key(keys_x, index_x); hw::ledger::log_hexbuffer("get_subaddress_spend_public_key: [[OUT]] derivation ", D_x.data, 32); #endif @@ -644,12 +697,7 @@ namespace hw { hw::ledger::check32("get_subaddress_spend_public_key", "D", D_x.data, D.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return D; + return D; } std::vector<crypto::public_key> device_ledger::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) { @@ -665,24 +713,22 @@ namespace hw { } cryptonote::account_public_address device_ledger::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) { - cryptonote::account_public_address address; - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + cryptonote::account_public_address address; + int offset; #ifdef DEBUG_HWDEVICE const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys); const cryptonote::subaddress_index index_x = index; cryptonote::account_public_address address_x; - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_public_key", keys_x.m_account_address.m_view_public_key.data, 32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_spend_public_key", keys_x.m_account_address.m_spend_public_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_view_public_key", keys_x.m_account_address.m_view_public_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[IN]] keys.m_spend_public_key", keys_x.m_account_address.m_spend_public_key.data, 32); hw::ledger::log_message ("get_subaddress: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor)); - this->controle_device->get_subaddress(keys_x, index_x, address_x); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_view_public_key ", address_x.m_view_public_key.data, 32); - hw::ledger::log_hexbuffer("derive_subaddress_public_key: [[IN]] keys.m_spend_public_key", address_x.m_spend_public_key.data, 32); + address_x = this->controle_device->get_subaddress(keys_x, index_x); + hw::ledger::log_hexbuffer("get_subaddress: [[OUT]] keys.m_view_public_key ", address_x.m_view_public_key.data, 32); + hw::ledger::log_hexbuffer("get_subaddress: [[OUT]] keys.m_spend_public_key", address_x.m_spend_public_key.data, 32); #endif if (index.is_zero()) { @@ -717,20 +763,13 @@ namespace hw { hw::ledger::check32("get_subaddress", "address.m_spend_public_key.data", address_x.m_spend_public_key.data, address.m_spend_public_key.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return address; + return address; } crypto::secret_key device_ledger::get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) { - crypto::secret_key sub_sec; - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + crypto::secret_key sub_sec; + int offset; #ifdef DEBUG_HWDEVICE const crypto::secret_key sec_x = hw::ledger::decrypt(sec); @@ -738,7 +777,7 @@ namespace hw { crypto::secret_key sub_sec_x; hw::ledger::log_message ("get_subaddress_secret_key: [[IN]] index ", std::to_string(index.major)+"."+std::to_string(index.minor)); hw::ledger::log_hexbuffer("get_subaddress_secret_key: [[IN]] sec ", sec_x.data, 32); - this->controle_device->get_subaddress_secret_key(sec_x, index_x, sub_sec_x); + sub_sec_x = this->controle_device->get_subaddress_secret_key(sec_x, index_x); hw::ledger::log_hexbuffer("get_subaddress_secret_key: [[OUT]] sub_sec", sub_sec_x.data, 32); #endif @@ -751,7 +790,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //sec memmove(this->buffer_send+offset, sec.data, 32); @@ -772,12 +811,7 @@ namespace hw { hw::ledger::check32("get_subaddress_secret_key", "sub_sec", sub_sec_x.data, sub_sec_clear.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return sub_sec; + return sub_sec; } /* ======================================================================= */ @@ -785,10 +819,9 @@ namespace hw { /* ======================================================================= */ bool device_ledger::verify_keys(const crypto::secret_key &secret_key, const crypto::public_key &public_key) { - lock_device(); - try { - int offset =0,sw; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset, sw; + reset_buffer(); this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_VERIFY_KEY; @@ -816,20 +849,12 @@ namespace hw { this->buffer_recv[2] << 8 | this->buffer_recv[3] << 0 ; - unlock_device(); return verified == 1; - }catch (...) { - unlock_device(); - throw; - } - return false; } bool device_ledger::scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const rct::key P_x = P; @@ -843,8 +868,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_SECRET_SCAL_MUL_KEY; this->buffer_send[2] = 0x00; @@ -852,7 +875,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //pub memmove(this->buffer_send+offset, P.bytes, 32); @@ -873,19 +896,12 @@ namespace hw { hw::ledger::check32("scalarmultKey", "mulkey", (char*)aP_x.bytes, (char*)aP.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::scalarmultBase(rct::key &aG, const rct::key &a) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const rct::key a_x = hw::ledger::decrypt(a); @@ -897,8 +913,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_SECRET_SCAL_MUL_BASE; this->buffer_send[2] = 0x00; @@ -906,7 +920,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //sec memmove(this->buffer_send+offset, a.bytes, 32); @@ -923,20 +937,12 @@ namespace hw { hw::ledger::check32("scalarmultBase", "mulkey", (char*)aG_x.bytes, (char*)aG.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::sc_secret_add( crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) { - - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const crypto::secret_key a_x = hw::ledger::decrypt(a); @@ -947,8 +953,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_SECRET_KEY_ADD; this->buffer_send[2] = 0x00; @@ -956,7 +960,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //sec key memmove(this->buffer_send+offset, a.data, 32); @@ -977,23 +981,16 @@ namespace hw { hw::ledger::check32("sc_secret_add", "r", r_x.data, r_clear.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } crypto::secret_key device_ledger::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover) { - if (recover) { - throw std::runtime_error("device generate key does not support recover"); - } + AUTO_LOCK_CMD(); + if (recover) { + throw std::runtime_error("device generate key does not support recover"); + } - lock_device(); - try { - int offset =0; - unsigned char options = 0; + int offset; #ifdef DEBUG_HWDEVICE bool recover_x = recover; @@ -1004,8 +1001,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_GENERATE_KEYPAIR; this->buffer_send[2] = 0x00; @@ -1013,7 +1008,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; this->buffer_send[4] = offset-5; @@ -1031,20 +1026,13 @@ namespace hw { hw::ledger::check32("generate_keys", "pub", pub_x.data, pub.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return sec; + return sec; } bool device_ledger::generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + bool r = false; #ifdef DEBUG_HWDEVICE const crypto::public_key pub_x = pub; @@ -1056,6 +1044,17 @@ namespace hw { hw::ledger::log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32); #endif + if ((this->mode == TRANSACTION_PARSE) && has_view_key) { + //A derivation is resquested in PASRE mode and we have the view key, + //so do that wihtout the device and return the derivation unencrypted. + MDEBUG( "generate_key_derivation : PARSE mode with known viewkey"); + //Note derivation in PARSE mode can only happen with viewkey, so assert it! + assert(is_fake_view_key(sec)); + r = crypto::generate_key_derivation(pub, this->viewkey, derivation); + } else { + + int offset; + reset_buffer(); this->buffer_send[0] = 0x00; @@ -1065,7 +1064,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //pub memmove(this->buffer_send+offset, pub.data, 32); @@ -1080,25 +1079,24 @@ namespace hw { //derivattion data memmove(derivation.data, &this->buffer_recv[0], 32); - - #ifdef DEBUG_HWDEVICE - crypto::key_derivation derivation_clear = hw::ledger::decrypt(derivation); - hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data); - #endif - - unlock_device(); - }catch (...) { - unlock_device(); - throw; + r = true; } - return true; + #ifdef DEBUG_HWDEVICE + crypto::key_derivation derivation_clear ; + if ((this->mode == TRANSACTION_PARSE) && has_view_key) { + derivation_clear = derivation; + }else { + derivation_clear = hw::ledger::decrypt(derivation); + } + hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data); + #endif + + return r; } bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) { - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; #ifdef DEBUG_HWDEVICE const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); @@ -1112,8 +1110,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_DERIVATION_TO_SCALAR; this->buffer_send[2] = 0x00; @@ -1121,7 +1117,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //derivattion memmove(this->buffer_send+offset, derivation.data, 32); @@ -1145,19 +1141,12 @@ namespace hw { hw::ledger::check32("derivation_to_scalar", "res", res_x.data, res_clear.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) { - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; #ifdef DEBUG_HWDEVICE const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); @@ -1173,8 +1162,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_DERIVE_SECRET_KEY; this->buffer_send[2] = 0x00; @@ -1182,7 +1169,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //derivation memmove(this->buffer_send+offset, derivation.data, 32); @@ -1209,20 +1196,13 @@ namespace hw { hw::ledger::check32("derive_secret_key", "derived_sec", derived_sec_x.data, derived_sec_clear.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub){ - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; - + #ifdef DEBUG_HWDEVICE const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation); const std::size_t output_index_x = output_index; @@ -1237,8 +1217,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_DERIVE_PUBLIC_KEY; this->buffer_send[2] = 0x00; @@ -1246,7 +1224,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //derivation memmove(this->buffer_send+offset, derivation.data, 32); @@ -1272,19 +1250,12 @@ namespace hw { hw::ledger::check32("derive_public_key", "derived_pub", derived_pub_x.data, derived_pub.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) { - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; #ifdef DEBUG_HWDEVICE const crypto::secret_key sec_x = hw::ledger::decrypt(sec); @@ -1299,8 +1270,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_SECRET_KEY_TO_PUBLIC_KEY; this->buffer_send[2] = 0x00; @@ -1308,7 +1277,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //sec key memmove(this->buffer_send+offset, sec.data, 32); @@ -1325,19 +1294,12 @@ namespace hw { hw::ledger::check32("secret_key_to_public_key", "pub", pub_x.data, pub.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image){ - lock_device(); - try { + AUTO_LOCK_CMD(); int offset; - unsigned char options; #ifdef DEBUG_HWDEVICE const crypto::public_key pub_x = pub; @@ -1351,8 +1313,6 @@ namespace hw { reset_buffer(); - options = 0; - this->buffer_send[0] = 0x00; this->buffer_send[1] = INS_GEN_KEY_IMAGE; this->buffer_send[2] = 0x00; @@ -1360,7 +1320,7 @@ namespace hw { this->buffer_send[4] = 0x00; offset = 5; //options - this->buffer_send[offset] = options; + this->buffer_send[offset] = 0; offset += 1; //pub memmove(this->buffer_send+offset, pub.data, 32); @@ -1380,12 +1340,7 @@ namespace hw { hw::ledger::check32("generate_key_image", "image", image_x.data, image.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } /* ======================================================================= */ @@ -1393,12 +1348,9 @@ namespace hw { /* ======================================================================= */ bool device_ledger::open_tx(crypto::secret_key &tx_key) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; - lock_tx(); reset_buffer(); key_map.clear(); @@ -1423,57 +1375,19 @@ namespace hw { this->exchange(); memmove(tx_key.data, &this->buffer_recv[32], 32); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; - } - - bool device_ledger::set_signature_mode(unsigned int sig_mode) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; - - reset_buffer(); - - this->buffer_send[0] = 0x00; - this->buffer_send[1] = INS_SET_SIGNATURE_MODE; - this->buffer_send[2] = 0x01; - this->buffer_send[3] = 0x00; - this->buffer_send[4] = 0x00; - offset = 5; - //options - this->buffer_send[offset] = 0x00; - offset += 1; - //account - this->buffer_send[offset] = sig_mode; - offset += 1; - - this->buffer_send[4] = offset-5; - this->length_send = offset; - this->exchange(); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + + return true; } bool device_ledger::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const crypto::public_key public_key_x = public_key; const crypto::secret_key secret_key_x = hw::ledger::decrypt(secret_key); crypto::hash8 payment_id_x = payment_id; - this->controle_device->encrypt_payment_id(public_key_x, secret_key_x, payment_id_x); + this->controle_device->encrypt_payment_id(payment_id_x, public_key_x, secret_key_x); #endif reset_buffer(); @@ -1506,32 +1420,19 @@ namespace hw { hw::ledger::check8("stealth", "payment_id", payment_id_x.data, payment_id.data); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const size_t real_output_index, const rct::key &amount_key, const crypto::public_key &out_eph_public_key) { - lock_device(); - try { + AUTO_LOCK_CMD(); key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), is_subaddress, real_output_index, rct::pk2rct(out_eph_public_key), amount_key)); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & AKout) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const rct::key AKout_x = hw::ledger::decrypt(AKout); @@ -1574,19 +1475,12 @@ namespace hw { hw::ledger::log_hexbuffer("Blind AKV input", (char*)&this->buffer_recv[64], 3*32); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::ecdhDecode(rct::ecdhTuple & masked, const rct::key & AKout) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; #ifdef DEBUG_HWDEVICE const rct::key AKout_x = hw::ledger::decrypt(AKout); @@ -1627,21 +1521,13 @@ namespace hw { hw::ledger::check32("ecdhDecode", "mask", (char*)masked_x.mask.bytes,(char*) masked.mask.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) { - - lock_device(); - try { - unsigned char options = 0; + AUTO_LOCK_CMD(); unsigned int data_offset, C_offset, kv_offset, i; const char *data; @@ -1834,21 +1720,15 @@ namespace hw { hw::ledger::check32("mlsag_prehash", "prehash", (char*)prehash_x.bytes, (char*)prehash.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::mlsag_prepare(const rct::key &H, const rct::key &xx, rct::key &a, rct::key &aG, rct::key &aHP, rct::key &II) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; + unsigned char options; #ifdef DEBUG_HWDEVICE const rct::key H_x = H; @@ -1897,19 +1777,13 @@ namespace hw { hw::ledger::check32("mlsag_prepare", "II", (char*)II_x.bytes, (char*)II.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::mlsag_prepare(rct::key &a, rct::key &aG) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; + unsigned char options; #ifdef DEBUG_HWDEVICE rct::key a_x; @@ -1941,19 +1815,13 @@ namespace hw { hw::ledger::check32("mlsag_prepare", "AG", (char*)aG_x.bytes, (char*)aG.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::mlsag_hash(const rct::keyV &long_message, rct::key &c) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; + unsigned char options; size_t cnt; #ifdef DEBUG_HWDEVICE @@ -1991,20 +1859,12 @@ namespace hw { hw::ledger::check32("mlsag_hash", "c", (char*)c_x.bytes, (char*)c.bytes); #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; - + return true; } bool device_ledger::mlsag_sign(const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss) { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; CHECK_AND_ASSERT_THROW_MES(dsRows<=rows, "dsRows greater than rows"); CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "xx size does not match rows"); @@ -2061,19 +1921,12 @@ namespace hw { } #endif - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } bool device_ledger::close_tx() { - lock_device(); - try { - int offset =0; - unsigned char options = 0; + AUTO_LOCK_CMD(); + int offset; reset_buffer(); @@ -2091,13 +1944,7 @@ namespace hw { this->length_send = offset; this->exchange(); - unlock_tx(); - unlock_device(); - }catch (...) { - unlock_device(); - throw; - } - return true; + return true; } /* ---------------------------------------------------------- */ diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index e06c5f72c..652cfb34b 100644 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -32,11 +32,11 @@ #include <cstddef> #include <string> -#include <mutex> #include "device.hpp" #include <PCSC/winscard.h> #include <PCSC/wintypes.h> - +#include <boost/thread/mutex.hpp> +#include <boost/thread/recursive_mutex.hpp> namespace hw { @@ -80,13 +80,11 @@ namespace hw { class device_ledger : public hw::device { private: - mutable std::mutex device_locker; - mutable std::mutex tx_locker; - void lock_device() ; - void unlock_device() ; - void lock_tx() ; - void unlock_tx() ; - + // Locker for concurrent access + mutable boost::recursive_mutex device_locker; + mutable boost::mutex command_locker; + + //PCSC management std::string full_name; SCARDCONTEXT hContext; SCARDHANDLE hCard; @@ -95,15 +93,21 @@ namespace hw { DWORD length_recv; BYTE buffer_recv[BUFFER_RECV_SIZE]; unsigned int id; - - Keymap key_map; - - void logCMD(void); void logRESP(void); unsigned int exchange(unsigned int ok=0x9000, unsigned int mask=0xFFFF); void reset_buffer(void); + // hw running mode + device_mode mode; + // map public destination key to ephemeral destination key + Keymap key_map; + + // To speed up blockchain parsing the view key maybe handle here. + crypto::secret_key viewkey; + bool has_view_key; + + //extra debug #ifdef DEBUG_HWDEVICE device *controle_device; #endif @@ -130,6 +134,15 @@ namespace hw { bool connect(void) override; bool disconnect() override; + bool set_mode(device_mode mode) override; + + /* ======================================================================= */ + /* LOCKER */ + /* ======================================================================= */ + void lock(void) override; + void unlock(void) override; + bool try_lock(void) override; + /* ======================================================================= */ /* WALLET & ADDRESS */ /* ======================================================================= */ @@ -168,8 +181,6 @@ namespace hw { bool open_tx(crypto::secret_key &tx_key) override; - bool set_signature_mode(unsigned int sig_mode) override; - bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) override; bool ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec) override; @@ -190,10 +201,9 @@ namespace hw { }; - #ifdef DEBUG_HWDEVICE - extern crypto::secret_key viewkey; - extern crypto::secret_key spendkey; + extern crypto::secret_key dbg_viewkey; + extern crypto::secret_key dbg_spendkey; #endif #endif //WITH_DEVICE_LEDGER diff --git a/src/device/log.cpp b/src/device/log.cpp index a2ad0f4f4..cbbcfc953 100644 --- a/src/device/log.cpp +++ b/src/device/log.cpp @@ -56,8 +56,8 @@ namespace hw { } #ifdef DEBUG_HWDEVICE - extern crypto::secret_key viewkey; - extern crypto::secret_key spendkey; + extern crypto::secret_key dbg_viewkey; + extern crypto::secret_key dbg_spendkey; void decrypt(char* buf, size_t len) { @@ -69,7 +69,7 @@ namespace hw { if (buf[i] != 0) break; } if (i == 32) { - memmove(buf, hw::ledger::viewkey.data, 32); + memmove(buf, hw::ledger::dbg_viewkey.data, 32); return; } //spend key? @@ -77,7 +77,7 @@ namespace hw { if (buf[i] != (char)0xff) break; } if (i == 32) { - memmove(buf, hw::ledger::spendkey.data, 32); + memmove(buf, hw::ledger::dbg_spendkey.data, 32); return; } } @@ -161,4 +161,4 @@ namespace hw { } #endif //WITH_DEVICE_LEDGER -}
\ No newline at end of file +} diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp index bde6fc88e..c9ca63f43 100644 --- a/src/p2p/net_node.cpp +++ b/src/p2p/net_node.cpp @@ -39,7 +39,7 @@ namespace nodetool , "Port for p2p network protocol" , std::to_string(config::P2P_DEFAULT_PORT) , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} - , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string { if (testnet_stagenet[0] && defaulted) return std::to_string(config::testnet::P2P_DEFAULT_PORT); else if (testnet_stagenet[1] && defaulted) diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 54875e619..3b0d1c394 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -397,8 +397,8 @@ namespace nodetool full_addrs.insert("163.172.182.165:18080"); full_addrs.insert("161.67.132.39:18080"); full_addrs.insert("198.74.231.92:18080"); - full_addrs.insert("195.154.123.123:28080"); - full_addrs.insert("212.83.172.165:28080"); + full_addrs.insert("195.154.123.123:18080"); + full_addrs.insert("212.83.172.165:18080"); } return full_addrs; } @@ -490,7 +490,7 @@ namespace nodetool if (result.size()) { for (const auto& addr_string : result) - full_addrs.insert(addr_string + ":18080"); + full_addrs.insert(addr_string + ":" + std::to_string(m_nettype == cryptonote::TESTNET ? ::config::testnet::P2P_DEFAULT_PORT : m_nettype == cryptonote::STAGENET ? ::config::stagenet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT)); } ++i; } diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index c3d1a9d11..69e527fd8 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -2117,7 +2117,7 @@ namespace cryptonote , "Port for RPC server" , std::to_string(config::RPC_DEFAULT_PORT) , {{ &cryptonote::arg_testnet_on, &cryptonote::arg_stagenet_on }} - , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) { + , [](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string { if (testnet_stagenet[0] && defaulted) return std::to_string(config::testnet::RPC_DEFAULT_PORT); else if (testnet_stagenet[1] && defaulted) diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h index a5755e062..86e41e047 100644 --- a/src/rpc/core_rpc_server.h +++ b/src/rpc/core_rpc_server.h @@ -153,7 +153,7 @@ namespace cryptonote MAP_JON_RPC_WE_IF("relay_tx", on_relay_tx, COMMAND_RPC_RELAY_TX, !m_restricted) MAP_JON_RPC_WE_IF("sync_info", on_sync_info, COMMAND_RPC_SYNC_INFO, !m_restricted) MAP_JON_RPC_WE("get_txpool_backlog", on_get_txpool_backlog, COMMAND_RPC_GET_TRANSACTION_POOL_BACKLOG) - MAP_JON_RPC_WE_IF("get_output_distribution", on_get_output_distribution, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION, !m_restricted) + MAP_JON_RPC_WE("get_output_distribution", on_get_output_distribution, COMMAND_RPC_GET_OUTPUT_DISTRIBUTION) END_JSON_RPC_MAP() END_URI_MAP2() diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 97dadb126..33615ffe2 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1650,6 +1650,9 @@ bool simple_wallet::set_default_ring_size(const std::vector<std::string> &args/* return true; } + if (ring_size != 0 && ring_size != DEFAULT_MIX+1) + message_writer() << tr("WARNING: this is a non default ring size, which may harm your privacy. Default is recommended."); + const auto pwd_container = get_and_verify_password(); if (pwd_container) { @@ -2974,6 +2977,22 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) // create wallet bool r = new_wallet(vm, "Ledger"); CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); + // if no block_height is specified, assume its a new account and start it "now" + if(m_wallet->get_refresh_from_block_height() == 0) { + { + tools::scoped_message_writer wrt = tools::msg_writer(); + wrt << tr("No restore height is specified."); + wrt << tr("Assumed you are creating a new account, restore will be done from current estimated blockchain height."); + wrt << tr("Use --restore-height if you want to restore an already setup account from a specific height"); + } + std::string confirm = input_line(tr("Is this okay? (Y/Yes/N/No): ")); + if (std::cin.eof() || !command_line::is_yes(confirm)) + CHECK_AND_ASSERT_MES(false, false, tr("account creation aborted")); + + m_wallet->set_refresh_from_block_height(m_wallet->estimate_blockchain_height()-1); + m_wallet->explicit_refresh_from_block_height(true); + m_restore_height = m_wallet->get_refresh_from_block_height(); + } } else { @@ -2990,7 +3009,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) CHECK_AND_ASSERT_MES(r, false, tr("account creation failed")); } - if (m_restoring && m_generate_from_json.empty()) + if (m_restoring && m_generate_from_json.empty() && m_generate_from_device.empty()) { m_wallet->explicit_refresh_from_block_height(!command_line::is_arg_defaulted(vm, arg_restore_height)); } @@ -3101,6 +3120,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) if (!m_trusted_daemon) message_writer() << (boost::format(tr("Warning: using an untrusted daemon at %s, privacy will be lessened")) % m_wallet->get_daemon_address()).str(); + if (m_wallet->get_ring_database().empty()) + fail_msg_writer() << tr("Failed to initialize ring database: privacy enhancing features will be inactive"); + m_wallet->callback(this); return true; @@ -3385,7 +3407,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm, try { m_wallet->restore(m_wallet_file, std::move(rc.second).password(), device_name); - message_writer(console_color_white, true) << tr("Generated new on device wallet: ") + message_writer(console_color_white, true) << tr("Generated new wallet on hw device: ") << m_wallet->get_account().get_public_address_str(m_wallet->nettype()); } catch (const std::exception& e) @@ -4581,6 +4603,23 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri if (!print_ring_members(ptx_vector, prompt)) return true; } + bool default_ring_size = true; + for (const auto &ptx: ptx_vector) + { + for (const auto &vin: ptx.tx.vin) + { + if (vin.type() == typeid(txin_to_key)) + { + const txin_to_key& in_to_key = boost::get<txin_to_key>(vin); + if (in_to_key.key_offsets.size() != DEFAULT_MIX + 1) + default_ring_size = false; + } + } + } + if (m_wallet->confirm_non_default_ring_size() && !default_ring_size) + { + prompt << tr("WARNING: this is a non default ring size, which may harm your privacy. Default is recommended."); + } prompt << ENDL << tr("Is this okay? (Y/Yes/N/No): "); std::string accepted = input_line(prompt.str()); @@ -7458,7 +7497,7 @@ int main(int argc, char* argv[]) const auto vm = wallet_args::main( argc, argv, "monero-wallet-cli [--wallet-file=<file>|--generate-new-wallet=<file>] [<COMMAND>]", - sw::tr("This is the command line monero wallet. It needs to connect to a monero\ndaemon to work correctly."), + sw::tr("This is the command line monero wallet. It needs to connect to a monero\ndaemon to work correctly.\nWARNING: Do not reuse your Monero keys on an another fork, UNLESS this fork has key reuse mitigations built in. Doing so will harm your privacy."), desc_params, positional_options, [](const std::string &s, bool emphasis){ tools::scoped_message_writer(emphasis ? epee::console_color_white : epee::console_color_default, true) << s; }, diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index b02884f67..b78a471b9 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -60,7 +60,7 @@ namespace Monero { namespace { // copy-pasted from simplewallet - static const size_t DEFAULT_MIXIN = 4; + static const size_t DEFAULT_MIXIN = 6; static const int DEFAULT_REFRESH_INTERVAL_MILLIS = 1000 * 10; // limit maximum refresh interval as one minute static const int MAX_REFRESH_INTERVAL_MILLIS = 1000 * 60 * 1; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 4b7e6dd93..8406ca543 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -110,7 +110,7 @@ using namespace cryptonote; #define MULTISIG_EXPORT_FILE_MAGIC "Monero multisig export\001" -#define SEGREGATION_FORK_HEIGHT 1564965 +#define SEGREGATION_FORK_HEIGHT 1546000 #define TESTNET_SEGREGATION_FORK_HEIGHT 1000000 #define STAGENET_SEGREGATION_FORK_HEIGHT 1000000 #define SEGREGATION_FORK_VICINITY 1500 /* blocks */ @@ -145,7 +145,7 @@ struct options { "shared-ringdb-dir", tools::wallet2::tr("Set shared ring database path"), get_default_ringdb_path(), testnet, - [](bool testnet, bool defaulted, std::string val) { + [](bool testnet, bool defaulted, std::string val)->std::string { if (testnet) return (boost::filesystem::path(val) / "testnet").string(); return val; @@ -653,6 +653,7 @@ wallet2::wallet2(network_type nettype, bool restricted): m_refresh_from_block_height(0), m_explicit_refresh_from_block_height(true), m_confirm_missing_payment_id(true), + m_confirm_non_default_ring_size(true), m_ask_password(true), m_min_output_count(0), m_min_output_value(0), @@ -1007,13 +1008,16 @@ void wallet2::set_unspent(size_t idx) //---------------------------------------------------------------------------------------------------- void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const { + hw::device &hwdev = m_account.get_device(); + std::unique_lock<hw::device> hwdev_lock (hwdev); + hwdev.set_mode(hw::device::TRANSACTION_PARSE); if (o.target.type() != typeid(txout_to_key)) { tx_scan_info.error = true; 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, m_account.get_device()); + tx_scan_info.received = is_out_to_acc_precomp(m_subaddresses, boost::get<txout_to_key>(o.target).key, derivation, additional_derivations, i, hwdev); if(tx_scan_info.received) { tx_scan_info.money_transfered = o.amount; // may be 0 for ringct outputs @@ -1080,9 +1084,15 @@ void wallet2::scan_output(const cryptonote::transaction &tx, const crypto::publi //---------------------------------------------------------------------------------------------------- void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen) { - // In this function, tx (probably) only contains the base information - // (that is, the prunable stuff may or may not be included) + //ensure device is let in NONE mode in any case + hw::device &hwdev = m_account.get_device(); + + std::unique_lock<hw::device> hwdev_lock (hwdev); + hw::reset_mode rst(hwdev); + hwdev_lock.unlock(); + // In this function, tx (probably) only contains the base information + // (that is, the prunable stuff may or may not be included) if (!miner_tx && !pool) process_unconfirmed(txid, tx, height); std::vector<size_t> outs; @@ -1119,8 +1129,10 @@ 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; + + hwdev_lock.lock(); + hwdev.set_mode(hw::device::TRANSACTION_PARSE); if (!hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, derivation)) { MWARNING("Failed to generate key derivation from tx pubkey, skipping"); @@ -1140,6 +1152,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote additional_derivations.pop_back(); } } + hwdev_lock.unlock(); if (miner_tx && m_refresh_type == RefreshNoCoinbase) { @@ -1161,16 +1174,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote std::ref(tx_scan_info[i]))); } waiter.wait(); - // then scan all outputs from 0 + hwdev_lock.lock(); + hwdev.set_mode(hw::device::NONE); for (size_t i = 0; i < tx.vout.size(); ++i) { THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); if (tx_scan_info[i].received) { + hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation); scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); } } + hwdev_lock.unlock(); } } else if (tx.vout.size() > 1 && tools::threadpool::getInstance().get_max_concurrency() > 1) @@ -1181,14 +1197,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote std::ref(tx_scan_info[i]))); } waiter.wait(); + + hwdev_lock.lock(); + hwdev.set_mode(hw::device::NONE); for (size_t i = 0; i < tx.vout.size(); ++i) { THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); if (tx_scan_info[i].received) { + hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation); scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); } } + hwdev_lock.unlock(); } else { @@ -1198,7 +1219,11 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys()); if (tx_scan_info[i].received) { + hwdev_lock.lock(); + hwdev.set_mode(hw::device::NONE); + hwdev.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation); scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); + hwdev_lock.unlock(); } } } @@ -2560,6 +2585,9 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable value2.SetInt(m_confirm_missing_payment_id ? 1 :0); json.AddMember("confirm_missing_payment_id", value2, json.GetAllocator()); + value2.SetInt(m_confirm_non_default_ring_size ? 1 :0); + json.AddMember("confirm_non_default_ring_size", value2, json.GetAllocator()); + value2.SetInt(m_ask_password ? 1 :0); json.AddMember("ask_password", value2, json.GetAllocator()); @@ -2661,6 +2689,7 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ m_auto_refresh = true; m_refresh_type = RefreshType::RefreshDefault; m_confirm_missing_payment_id = true; + m_confirm_non_default_ring_size = true; m_ask_password = true; m_min_output_count = 0; m_min_output_value = 0; @@ -2669,6 +2698,9 @@ 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_segregate_pre_fork_outputs = true; + m_key_reuse_mitigation2 = true; + m_segregation_height = 0; m_key_on_device = false; } else if(json.IsObject()) @@ -2761,6 +2793,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ m_refresh_from_block_height = field_refresh_height; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, confirm_missing_payment_id, int, Int, false, true); m_confirm_missing_payment_id = field_confirm_missing_payment_id; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, confirm_non_default_ring_size, int, Int, false, true); + m_confirm_non_default_ring_size = field_confirm_non_default_ring_size; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, ask_password, int, Int, false, true); m_ask_password = field_ask_password; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, default_decimal_point, int, Int, false, CRYPTONOTE_DISPLAY_DECIMAL_POINT); @@ -2785,6 +2819,12 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ (boost::format("%s wallet cannot be opened as %s wallet") % (field_nettype == 0 ? "Mainnet" : field_nettype == 1 ? "Testnet" : "Stagenet") % (m_nettype == MAINNET ? "mainnet" : m_nettype == TESTNET ? "testnet" : "stagenet")).str()); + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, segregate_pre_fork_outputs, int, Int, false, true); + m_segregate_pre_fork_outputs = field_segregate_pre_fork_outputs; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, key_reuse_mitigation2, int, Int, false, true); + m_key_reuse_mitigation2 = field_key_reuse_mitigation2; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, segregation_height, int, Uint, false, 0); + m_segregation_height = field_segregation_height; } else { @@ -5467,45 +5507,61 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<crypto } } -void wallet2::set_ring_database(const std::string &filename) +bool wallet2::set_ring_database(const std::string &filename) { m_ring_database = filename; MINFO("ringdb path set to " << filename); m_ringdb.reset(); - cryptonote::block b; - generate_genesis(b); if (!m_ring_database.empty()) - m_ringdb.reset(new tools::ringdb(m_ring_database, epee::string_tools::pod_to_hex(get_block_hash(b)))); + { + try + { + cryptonote::block b; + generate_genesis(b); + m_ringdb.reset(new tools::ringdb(m_ring_database, epee::string_tools::pod_to_hex(get_block_hash(b)))); + } + catch (const std::exception &e) + { + MERROR("Failed to initialize ringdb: " << e.what()); + m_ring_database = ""; + return false; + } + } + return true; } bool wallet2::add_rings(const crypto::chacha_key &key, const cryptonote::transaction_prefix &tx) { if (!m_ringdb) - return true; - return m_ringdb->add_rings(key, tx); + return false; + try { return m_ringdb->add_rings(key, tx); } + catch (const std::exception &e) { return false; } } bool wallet2::add_rings(const cryptonote::transaction_prefix &tx) { crypto::chacha_key key; generate_chacha_key_from_secret_keys(key); - return add_rings(key, tx); + try { return add_rings(key, tx); } + catch (const std::exception &e) { return false; } } bool wallet2::remove_rings(const cryptonote::transaction_prefix &tx) { if (!m_ringdb) - return true; + return false; crypto::chacha_key key; generate_chacha_key_from_secret_keys(key); - return m_ringdb->remove_rings(key, tx); + try { return m_ringdb->remove_rings(key, tx); } + catch (const std::exception &e) { return false; } } bool wallet2::get_ring(const crypto::chacha_key &key, const crypto::key_image &key_image, std::vector<uint64_t> &outs) { if (!m_ringdb) - return true; - return m_ringdb->get_ring(key, key_image, outs); + return false; + try { return m_ringdb->get_ring(key, key_image, outs); } + catch (const std::exception &e) { return false; } } bool wallet2::get_rings(const crypto::hash &txid, std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &outs) @@ -5536,18 +5592,20 @@ bool wallet2::get_ring(const crypto::key_image &key_image, std::vector<uint64_t> crypto::chacha_key key; generate_chacha_key_from_secret_keys(key); - return get_ring(key, key_image, outs); + try { return get_ring(key, key_image, outs); } + catch (const std::exception &e) { return false; } } bool wallet2::set_ring(const crypto::key_image &key_image, const std::vector<uint64_t> &outs, bool relative) { if (!m_ringdb) - return true; + return false; crypto::chacha_key key; generate_chacha_key_from_secret_keys(key); - return m_ringdb->set_ring(key, key_image, outs, relative); + try { return m_ringdb->set_ring(key, key_image, outs, relative); } + catch (const std::exception &e) { return false; } } bool wallet2::find_and_save_rings(bool force) @@ -5555,7 +5613,7 @@ bool wallet2::find_and_save_rings(bool force) if (!force && m_ring_history_saved) return true; if (!m_ringdb) - return true; + return false; COMMAND_RPC_GET_TRANSACTIONS::request req = AUTO_VAL_INIT(req); COMMAND_RPC_GET_TRANSACTIONS::response res = AUTO_VAL_INIT(res); @@ -5614,34 +5672,41 @@ bool wallet2::find_and_save_rings(bool force) bool wallet2::blackball_output(const crypto::public_key &output) { if (!m_ringdb) - return true; - return m_ringdb->blackball(output); + return false; + try { return m_ringdb->blackball(output); } + catch (const std::exception &e) { return false; } } bool wallet2::set_blackballed_outputs(const std::vector<crypto::public_key> &outputs, bool add) { if (!m_ringdb) - return true; - bool ret = true; - if (!add) - ret &= m_ringdb->clear_blackballs(); - for (const auto &output: outputs) - ret &= m_ringdb->blackball(output); - return ret; + return false; + try + { + bool ret = true; + if (!add) + ret &= m_ringdb->clear_blackballs(); + for (const auto &output: outputs) + ret &= m_ringdb->blackball(output); + return ret; + } + catch (const std::exception &e) { return false; } } bool wallet2::unblackball_output(const crypto::public_key &output) { if (!m_ringdb) - return true; - return m_ringdb->unblackball(output); + return false; + try { return m_ringdb->unblackball(output); } + catch (const std::exception &e) { return false; } } bool wallet2::is_output_blackballed(const crypto::public_key &output) const { if (!m_ringdb) - return true; - return m_ringdb->blackballed(output); + return false; + try { return m_ringdb->blackballed(output); } + catch (const std::exception &e) { return false; } } bool wallet2::tx_add_fake_output(std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, uint64_t global_index, const crypto::public_key& output_public_key, const rct::key& mask, uint64_t real_index, bool unlocked) const @@ -5785,6 +5850,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> boost::optional<std::string> result = m_node_rpc_proxy.get_height(height); throw_on_rpc_response_error(result, "get_info"); bool is_shortly_after_segregation_fork = height >= segregation_fork_height && height < segregation_fork_height + SEGREGATION_FORK_VICINITY; + bool is_after_segregation_fork = height >= segregation_fork_height; // get histogram for the amounts we need cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request req_t = AUTO_VAL_INIT(req_t); @@ -5805,7 +5871,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> // if we want to segregate fake outs pre or post fork, get distribution std::unordered_map<uint64_t, std::pair<uint64_t, uint64_t>> segregation_limit; - if (m_segregate_pre_fork_outputs || m_key_reuse_mitigation2) + if (is_after_segregation_fork && (m_segregate_pre_fork_outputs || m_key_reuse_mitigation2)) { cryptonote::COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::request req_t = AUTO_VAL_INIT(req_t); cryptonote::COMMAND_RPC_GET_OUTPUT_DISTRIBUTION::response resp_t = AUTO_VAL_INIT(resp_t); @@ -5814,7 +5880,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> std::sort(req_t.amounts.begin(), req_t.amounts.end()); auto end = std::unique(req_t.amounts.begin(), req_t.amounts.end()); req_t.amounts.resize(std::distance(req_t.amounts.begin(), end)); - req_t.from_height = segregation_fork_height >= RECENT_OUTPUT_ZONE ? height >= (segregation_fork_height ? segregation_fork_height : height) - RECENT_OUTPUT_BLOCKS : 0; + req_t.from_height = std::max<uint64_t>(segregation_fork_height, RECENT_OUTPUT_BLOCKS) - RECENT_OUTPUT_BLOCKS; req_t.cumulative = true; m_daemon_rpc_mutex.lock(); bool r = net_utils::invoke_http_json_rpc("/json_rpc", "get_output_distribution", req_t, resp_t, m_http_client, rpc_timeout); @@ -5872,7 +5938,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> float pre_fork_num_out_ratio = 0.0f; float post_fork_num_out_ratio = 0.0f; - if (m_segregate_pre_fork_outputs && output_is_pre_fork) + if (is_after_segregation_fork && m_segregate_pre_fork_outputs && output_is_pre_fork) { num_outs = segregation_limit[amount].first; num_recent_outs = segregation_limit[amount].second; @@ -5892,7 +5958,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> break; } } - if (m_key_reuse_mitigation2) + if (is_after_segregation_fork && m_key_reuse_mitigation2) { if (output_is_pre_fork) { @@ -6107,7 +6173,7 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>> uint64_t num_outs = 0; const uint64_t amount = td.is_rct() ? 0 : td.amount(); const bool output_is_pre_fork = td.m_block_height < segregation_fork_height; - if (m_segregate_pre_fork_outputs && output_is_pre_fork) + if (is_after_segregation_fork && m_segregate_pre_fork_outputs && output_is_pre_fork) num_outs = segregation_limit[amount].first; else for (const auto &he: resp_t.histogram) { @@ -7224,6 +7290,11 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image, // usable balance. std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, bool trusted_daemon) { + //ensure device is let in NONE mode in any case + hw::device &hwdev = m_account.get_device(); + std::unique_lock<hw::device> hwdev_lock (hwdev); + hw::reset_mode rst(hwdev); + if(m_light_wallet) { // Populate m_transfers light_wallet_get_unspent_outs(); @@ -7441,8 +7512,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); + + hwdev.set_mode(hw::device::TRANSACTION_CREATE_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(); @@ -7671,7 +7742,7 @@ skip_tx: LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) << " total fee, " << print_money(accumulated_change) << " total change"); - hwdev.set_signature_mode(hw::device::SIGNATURE_REAL); + hwdev.set_mode(hw::device::TRANSACTION_CREATE_REAL); for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i) { TX &tx = *i; @@ -7802,6 +7873,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_single(const crypt std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra, bool trusted_daemon) { + //ensure device is let in NONE mode in any case + hw::device &hwdev = m_account.get_device(); + std::unique_lock<hw::device> hwdev_lock (hwdev); + hw::reset_mode rst(hwdev); + uint64_t accumulated_fee, accumulated_outputs, accumulated_change; struct TX { std::vector<size_t> selected_transfers; @@ -7834,8 +7910,7 @@ 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); + hwdev.set_mode(hw::device::TRANSACTION_CREATE_FAKE); while (!unused_dust_indices.empty() || !unused_transfers_indices.empty()) { TX &tx = txes.back(); @@ -7921,7 +7996,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton LOG_PRINT_L1("Done creating " << txes.size() << " transactions, " << print_money(accumulated_fee) << " total fee, " << print_money(accumulated_change) << " total change"); - hwdev.set_signature_mode(hw::device::SIGNATURE_REAL); + hwdev.set_mode(hw::device::TRANSACTION_CREATE_REAL); for (std::vector<TX>::iterator i = txes.begin(); i != txes.end(); ++i) { TX &tx = *i; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index abc7bb538..69b63876a 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -874,6 +874,8 @@ namespace tools void key_reuse_mitigation2(bool value) { m_key_reuse_mitigation2 = value; } uint64_t segregation_height() const { return m_segregation_height; } void segregation_height(uint64_t height) { m_segregation_height = height; } + bool confirm_non_default_ring_size() const { return m_confirm_non_default_ring_size; } + void confirm_non_default_ring_size(bool always) { m_confirm_non_default_ring_size = always; } bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const; void 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); @@ -1061,7 +1063,7 @@ namespace tools return epee::net_utils::invoke_http_json_rpc(uri, method_name, req, res, m_http_client, timeout, http_method, req_id); } - void set_ring_database(const std::string &filename); + bool set_ring_database(const std::string &filename); const std::string get_ring_database() const { return m_ring_database; } bool get_ring(const crypto::key_image &key_image, std::vector<uint64_t> &outs); bool get_rings(const crypto::hash &txid, std::vector<std::pair<crypto::key_image, std::vector<uint64_t>>> &outs); @@ -1194,6 +1196,7 @@ namespace tools // m_refresh_from_block_height was defaulted to zero.*/ bool m_explicit_refresh_from_block_height; bool m_confirm_missing_payment_id; + bool m_confirm_non_default_ring_size; bool m_ask_password; uint32_t m_min_output_count; uint64_t m_min_output_value; |