diff options
-rw-r--r-- | src/common/dns_utils.cpp | 2 | ||||
-rw-r--r-- | src/common/util.cpp | 5 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_tx_utils.cpp | 5 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.cpp | 43 | ||||
-rw-r--r-- | src/device/device.hpp | 1 | ||||
-rw-r--r-- | src/device/device_default.cpp | 4 | ||||
-rw-r--r-- | src/device/device_default.hpp | 1 | ||||
-rw-r--r-- | src/device/device_ledger.cpp | 23 | ||||
-rw-r--r-- | src/device/device_ledger.hpp | 1 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 20 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 2 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 22 | ||||
-rw-r--r-- | src/wallet/api/wallet.cpp | 2 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 118 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 3 |
15 files changed, 183 insertions, 69 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/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/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 0af9737a7..5dfbc1dd4 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1268,24 +1268,33 @@ namespace cryptonote m_spent_key_images.clear(); m_txpool_size = 0; std::vector<crypto::hash> remove; - bool r = m_blockchain.for_all_txpool_txes([this, &remove](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) { - cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(*bd, tx)) - { - MWARNING("Failed to parse tx from txpool, removing"); - remove.push_back(txid); - } - if (!insert_key_images(tx, meta.kept_by_block)) - { - MFATAL("Failed to insert key images from txpool tx"); + + // first add the not kept by block, then the kept by block, + // to avoid rejection due to key image collision + for (int pass = 0; pass < 2; ++pass) + { + const bool kept = pass == 1; + bool r = m_blockchain.for_all_txpool_txes([this, &remove, kept](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd) { + if (!!kept != !!meta.kept_by_block) + return true; + cryptonote::transaction tx; + if (!parse_and_validate_tx_from_blob(*bd, tx)) + { + MWARNING("Failed to parse tx from txpool, removing"); + remove.push_back(txid); + } + if (!insert_key_images(tx, meta.kept_by_block)) + { + MFATAL("Failed to insert key images from txpool tx"); + return false; + } + m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.blob_size, meta.receive_time), txid); + m_txpool_size += meta.blob_size; + return true; + }, true); + if (!r) return false; - } - m_txs_by_fee_and_receive_time.emplace(std::pair<double, time_t>(meta.fee / (double)meta.blob_size, meta.receive_time), txid); - m_txpool_size += meta.blob_size; - return true; - }, true); - if (!r) - return false; + } if (!remove.empty()) { LockedTXN lock(m_blockchain); diff --git a/src/device/device.hpp b/src/device/device.hpp index db489ff0c..9df0cb39d 100644 --- a/src/device/device.hpp +++ b/src/device/device.hpp @@ -145,6 +145,7 @@ namespace hw { virtual bool sc_secret_add( crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) = 0; virtual crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) = 0; virtual bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) = 0; + virtual bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations) = 0; virtual bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) = 0; virtual bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) = 0; virtual bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) = 0; diff --git a/src/device/device_default.cpp b/src/device/device_default.cpp index 56bd1e164..0071f7d4f 100644 --- a/src/device/device_default.cpp +++ b/src/device/device_default.cpp @@ -264,6 +264,10 @@ namespace hw { return true; } + bool device_default::conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations){ + return true; + } + /* ======================================================================= */ /* TRANSACTION */ /* ======================================================================= */ diff --git a/src/device/device_default.hpp b/src/device/device_default.hpp index 53942f53a..649fed862 100644 --- a/src/device/device_default.hpp +++ b/src/device/device_default.hpp @@ -93,6 +93,7 @@ namespace hw { bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) override; crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) override; bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override; + bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations); bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override; bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override; bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override; diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp index ee1497438..3b9ab6744 100644 --- a/src/device/device_ledger.cpp +++ b/src/device/device_ledger.cpp @@ -56,6 +56,7 @@ namespace hw { #define ASSERT_RV(rv) CHECK_AND_ASSERT_THROW_MES((rv)==SCARD_S_SUCCESS, "Fail SCard API : (" << (rv) << ") "<< pcsc_stringify_error(rv)<<" Device="<<this->id<<", hCard="<<hCard<<", hContext="<<hContext); #define ASSERT_SW(sw,ok,msk) CHECK_AND_ASSERT_THROW_MES(((sw)&(mask))==(ok), "Wrong Device Status : SW=" << std::hex << (sw) << " (EXPECT=" << std::hex << (ok) << ", MASK=" << std::hex << (mask) << ")") ; #define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ; + #define ASSERT_X(exp,msg) CHECK_AND_ASSERT_THROW_MES(exp, msg); #ifdef DEBUG_HWDEVICE crypto::secret_key dbg_viewkey; @@ -125,6 +126,10 @@ namespace hw { return sec == crypto::null_skey; } + bool operator==(const crypto::key_derivation &d0, const crypto::key_derivation &d1) { + return !memcmp(&d0, &d1, sizeof(d0)); + } + /* ===================================================================== */ /* === Device ==== */ /* ===================================================================== */ @@ -1094,6 +1099,24 @@ namespace hw { return r; } + bool device_ledger::conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations) { + const crypto::public_key *pkey=NULL; + if (derivation == main_derivation) { + pkey = &tx_pub_key; + MDEBUG("conceal derivation with main tx pub key"); + } else { + for(size_t n=0; n < additional_derivations.size();++n) { + if(derivation == additional_derivations[n]) { + pkey = &additional_tx_pub_keys[n]; + MDEBUG("conceal derivation with additionnal tx pub key"); + break; + } + } + } + ASSERT_X(pkey, "Mismatched derivation on scan info"); + return this->generate_key_derivation(*pkey, crypto::null_skey, derivation); + } + bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) { AUTO_LOCK_CMD(); int offset; diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp index 652cfb34b..9f73bd070 100644 --- a/src/device/device_ledger.hpp +++ b/src/device/device_ledger.hpp @@ -169,6 +169,7 @@ namespace hw { bool sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) override; crypto::secret_key generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false) override; bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override; + bool conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations); bool derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) override; bool derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) override; bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override; diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 69e527fd8..79792e387 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -209,6 +209,15 @@ namespace cryptonote return true; } //------------------------------------------------------------------------------------------------------------------------------ + static cryptonote::blobdata get_pruned_tx_blob(cryptonote::transaction &tx) + { + std::stringstream ss; + binary_archive<true> ba(ss); + bool r = tx.serialize_base(ba); + CHECK_AND_ASSERT_MES(r, cryptonote::blobdata(), "Failed to serialize rct signatures base"); + return ss.str(); + } + //------------------------------------------------------------------------------------------------------------------------------ static cryptonote::blobdata get_pruned_tx_blob(const cryptonote::blobdata &blobdata) { cryptonote::transaction tx; @@ -216,14 +225,9 @@ namespace cryptonote if (!cryptonote::parse_and_validate_tx_from_blob(blobdata, tx)) { MERROR("Failed to parse and validate tx from blob"); - return blobdata; + return cryptonote::blobdata(); } - - std::stringstream ss; - binary_archive<true> ba(ss); - bool r = tx.serialize_base(ba); - CHECK_AND_ASSERT_MES(r, blobdata, "Failed to serialize rct signatures base"); - return ss.str(); + return get_pruned_tx_blob(tx); } //------------------------------------------------------------------------------------------------------------------------------ bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res) @@ -633,7 +637,7 @@ namespace cryptonote crypto::hash tx_hash = *vhi++; e.tx_hash = *txhi++; - blobdata blob = t_serializable_object_to_blob(tx); + blobdata blob = req.prune ? get_pruned_tx_blob(tx) : t_serializable_object_to_blob(tx); e.as_hex = string_tools::buff_to_hex_nodelimer(blob); if (req.decode_as_json) e.as_json = obj_to_json_str(tx); diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 660fb7889..df5b4893f 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -563,10 +563,12 @@ namespace cryptonote { std::list<std::string> txs_hashes; bool decode_as_json; + bool prune; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(txs_hashes) KV_SERIALIZE(decode_as_json) + KV_SERIALIZE_OPT(prune, false) END_KV_SERIALIZE_MAP() }; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index b2651026f..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) { @@ -4600,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()); @@ -7477,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 b06444132..3883de6d9 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 */ @@ -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), @@ -1008,7 +1009,7 @@ 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); + boost::unique_lock<hw::device> hwdev_lock (hwdev); hwdev.set_mode(hw::device::TRANSACTION_PARSE); if (o.target.type() != typeid(txout_to_key)) { @@ -1086,7 +1087,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote //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); + boost::unique_lock<hw::device> hwdev_lock (hwdev); hw::reset_mode rst(hwdev); hwdev_lock.unlock(); @@ -1181,7 +1182,7 @@ 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.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation); + hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys, derivation, additional_derivations); scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); } } @@ -1204,7 +1205,7 @@ 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.generate_key_derivation(tx_pub_key, keys.m_view_secret_key, tx_scan_info[i].received->derivation); + hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys, derivation, additional_derivations); scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); } } @@ -1220,7 +1221,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote { 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); + hwdev.conceal_derivation(tx_scan_info[i].received->derivation, tx_pub_key, additional_tx_pub_keys, derivation, additional_derivations); scan_output(tx, tx_pub_key, i, tx_scan_info[i], num_vouts_received, tx_money_got_in_outs, outs); hwdev_lock.unlock(); } @@ -2034,6 +2035,7 @@ void wallet2::update_pool_state(bool refreshed) req.txs_hashes.push_back(epee::string_tools::pod_to_hex(p.first)); MDEBUG("asking for " << txids.size() << " transactions"); req.decode_as_json = false; + req.prune = false; m_daemon_rpc_mutex.lock(); bool r = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client, rpc_timeout); m_daemon_rpc_mutex.unlock(); @@ -2584,6 +2586,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()); @@ -2623,6 +2628,12 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable value2.SetUint(m_segregation_height); json.AddMember("segregation_height", value2, json.GetAllocator()); + value2.SetUint(m_subaddress_lookahead_major); + json.AddMember("subaddress_lookahead_major", value2, json.GetAllocator()); + + value2.SetUint(m_subaddress_lookahead_minor); + json.AddMember("subaddress_lookahead_minor", value2, json.GetAllocator()); + // Serialize the JSON object rapidjson::StringBuffer buffer; rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); @@ -2685,6 +2696,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; @@ -2696,6 +2708,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ m_segregate_pre_fork_outputs = true; m_key_reuse_mitigation2 = true; m_segregation_height = 0; + m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR; + m_subaddress_lookahead_minor = SUBADDRESS_LOOKAHEAD_MINOR; m_key_on_device = false; } else if(json.IsObject()) @@ -2788,6 +2802,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); @@ -2818,6 +2834,10 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_ 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; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, subaddress_lookahead_major, uint32_t, Uint, false, SUBADDRESS_LOOKAHEAD_MAJOR); + m_subaddress_lookahead_major = field_subaddress_lookahead_major; + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, subaddress_lookahead_minor, uint32_t, Uint, false, SUBADDRESS_LOOKAHEAD_MINOR); + m_subaddress_lookahead_minor = field_subaddress_lookahead_minor; } else { @@ -5526,7 +5546,7 @@ bool wallet2::set_ring_database(const std::string &filename) bool wallet2::add_rings(const crypto::chacha_key &key, const cryptonote::transaction_prefix &tx) { if (!m_ringdb) - return true; + return false; try { return m_ringdb->add_rings(key, tx); } catch (const std::exception &e) { return false; } } @@ -5542,7 +5562,7 @@ bool wallet2::add_rings(const cryptonote::transaction_prefix &tx) 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); try { return m_ringdb->remove_rings(key, tx); } @@ -5552,7 +5572,7 @@ bool wallet2::remove_rings(const cryptonote::transaction_prefix &tx) 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 false; try { return m_ringdb->get_ring(key, key_image, outs); } catch (const std::exception &e) { return false; } } @@ -5592,7 +5612,7 @@ bool wallet2::get_ring(const crypto::key_image &key_image, std::vector<uint64_t> 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); @@ -5606,7 +5626,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,39 +5634,49 @@ bool wallet2::find_and_save_rings(bool force) MDEBUG("Finding and saving rings..."); // get payments we made + std::vector<crypto::hash> txs_hashes; std::list<std::pair<crypto::hash,wallet2::confirmed_transfer_details>> payments; get_payments_out(payments, 0, std::numeric_limits<uint64_t>::max(), boost::none, std::set<uint32_t>()); for (const std::pair<crypto::hash,wallet2::confirmed_transfer_details> &entry: payments) { const crypto::hash &txid = entry.first; - req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); + txs_hashes.push_back(txid); } - MDEBUG("Found " << std::to_string(req.txs_hashes.size()) << " transactions"); - - // get those transactions from the daemon - req.decode_as_json = false; - bool r; - { - const boost::lock_guard<boost::mutex> lock{m_daemon_rpc_mutex}; - r = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client, rpc_timeout); - } - THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gettransactions"); - THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gettransactions"); - THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::wallet_internal_error, "gettransactions"); - THROW_WALLET_EXCEPTION_IF(res.txs.size() != req.txs_hashes.size(), error::wallet_internal_error, - "daemon returned wrong response for gettransactions, wrong txs count = " + - std::to_string(res.txs.size()) + ", expected " + std::to_string(req.txs_hashes.size())); - - MDEBUG("Scanning " << res.txs.size() << " transactions"); + MDEBUG("Found " << std::to_string(txs_hashes.size()) << " transactions"); crypto::chacha_key key; generate_chacha_key_from_secret_keys(key); - auto it = req.txs_hashes.begin(); - for (size_t i = 0; i < res.txs.size(); ++i, ++it) + // get those transactions from the daemon + static const size_t SLICE_SIZE = 200; + for (size_t slice = 0; slice < txs_hashes.size(); slice += SLICE_SIZE) { + req.decode_as_json = false; + req.prune = true; + req.txs_hashes.clear(); + size_t ntxes = slice + SLICE_SIZE > txs_hashes.size() ? txs_hashes.size() - slice : SLICE_SIZE; + for (size_t s = slice; s < slice + ntxes; ++s) + req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txs_hashes[s])); + bool r; + { + const boost::lock_guard<boost::mutex> lock{m_daemon_rpc_mutex}; + r = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client, rpc_timeout); + } + THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gettransactions"); + THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gettransactions"); + THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::wallet_internal_error, "gettransactions"); + THROW_WALLET_EXCEPTION_IF(res.txs.size() != req.txs_hashes.size(), error::wallet_internal_error, + "daemon returned wrong response for gettransactions, wrong txs count = " + + std::to_string(res.txs.size()) + ", expected " + std::to_string(req.txs_hashes.size())); + + MDEBUG("Scanning " << res.txs.size() << " transactions"); + THROW_WALLET_EXCEPTION_IF(slice + res.txs.size() > txs_hashes.size(), error::wallet_internal_error, "Unexpected tx array size"); + auto it = req.txs_hashes.begin(); + for (size_t i = 0; i < res.txs.size(); ++i, ++it) + { const auto &tx_info = res.txs[i]; + THROW_WALLET_EXCEPTION_IF(tx_info.tx_hash != epee::string_tools::pod_to_hex(txs_hashes[slice + i]), error::wallet_internal_error, "Wrong txid received"); THROW_WALLET_EXCEPTION_IF(tx_info.tx_hash != *it, error::wallet_internal_error, "Wrong txid received"); cryptonote::blobdata bd; THROW_WALLET_EXCEPTION_IF(!epee::string_tools::parse_hexstr_to_binbuff(tx_info.as_hex, bd), error::wallet_internal_error, "failed to parse tx from hexstr"); @@ -5655,9 +5685,10 @@ bool wallet2::find_and_save_rings(bool force) THROW_WALLET_EXCEPTION_IF(!cryptonote::parse_and_validate_tx_from_blob(bd, tx, tx_hash, tx_prefix_hash), error::wallet_internal_error, "failed to parse tx from blob"); THROW_WALLET_EXCEPTION_IF(epee::string_tools::pod_to_hex(tx_hash) != tx_info.tx_hash, error::wallet_internal_error, "txid mismatch"); THROW_WALLET_EXCEPTION_IF(!add_rings(key, tx), error::wallet_internal_error, "Failed to save ring"); + } } - MINFO("Found and saved rings for " << res.txs.size() << " transactions"); + MINFO("Found and saved rings for " << txs_hashes.size() << " transactions"); m_ring_history_saved = true; return true; } @@ -5665,7 +5696,7 @@ bool wallet2::find_and_save_rings(bool force) bool wallet2::blackball_output(const crypto::public_key &output) { if (!m_ringdb) - return true; + return false; try { return m_ringdb->blackball(output); } catch (const std::exception &e) { return false; } } @@ -5673,7 +5704,7 @@ bool wallet2::blackball_output(const crypto::public_key &output) bool wallet2::set_blackballed_outputs(const std::vector<crypto::public_key> &outputs, bool add) { if (!m_ringdb) - return true; + return false; try { bool ret = true; @@ -5689,7 +5720,7 @@ bool wallet2::set_blackballed_outputs(const std::vector<crypto::public_key> &out bool wallet2::unblackball_output(const crypto::public_key &output) { if (!m_ringdb) - return true; + return false; try { return m_ringdb->unblackball(output); } catch (const std::exception &e) { return false; } } @@ -5697,7 +5728,7 @@ bool wallet2::unblackball_output(const crypto::public_key &output) bool wallet2::is_output_blackballed(const crypto::public_key &output) const { if (!m_ringdb) - return true; + return false; try { return m_ringdb->blackballed(output); } catch (const std::exception &e) { return false; } } @@ -7285,7 +7316,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp { //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); + boost::unique_lock<hw::device> hwdev_lock (hwdev); hw::reset_mode rst(hwdev); if(m_light_wallet) { @@ -7868,7 +7899,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton { //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); + boost::unique_lock<hw::device> hwdev_lock (hwdev); hw::reset_mode rst(hwdev); uint64_t accumulated_fee, accumulated_outputs, accumulated_change; @@ -8223,6 +8254,7 @@ std::string wallet2::get_spend_proof(const crypto::hash &txid, const std::string COMMAND_RPC_GET_TRANSACTIONS::request req = AUTO_VAL_INIT(req); req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); req.decode_as_json = false; + req.prune = false; COMMAND_RPC_GET_TRANSACTIONS::response res = AUTO_VAL_INIT(res); bool r; { @@ -8342,6 +8374,7 @@ bool wallet2::check_spend_proof(const crypto::hash &txid, const std::string &mes COMMAND_RPC_GET_TRANSACTIONS::request req = AUTO_VAL_INIT(req); req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); req.decode_as_json = false; + req.prune = false; COMMAND_RPC_GET_TRANSACTIONS::response res = AUTO_VAL_INIT(res); bool r; { @@ -8464,6 +8497,8 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de COMMAND_RPC_GET_TRANSACTIONS::request req; COMMAND_RPC_GET_TRANSACTIONS::response res; req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); + req.decode_as_json = false; + req.prune = false; m_daemon_rpc_mutex.lock(); bool ok = epee::net_utils::invoke_http_json("/gettransactions", req, res, m_http_client); m_daemon_rpc_mutex.unlock(); @@ -8600,6 +8635,8 @@ std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::ac COMMAND_RPC_GET_TRANSACTIONS::request req; COMMAND_RPC_GET_TRANSACTIONS::response res; req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); + req.decode_as_json = false; + req.prune = false; m_daemon_rpc_mutex.lock(); bool ok = net_utils::invoke_http_json("/gettransactions", req, res, m_http_client); m_daemon_rpc_mutex.unlock(); @@ -8710,6 +8747,8 @@ bool wallet2::check_tx_proof(const crypto::hash &txid, const cryptonote::account COMMAND_RPC_GET_TRANSACTIONS::request req; COMMAND_RPC_GET_TRANSACTIONS::response res; req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid)); + req.decode_as_json = false; + req.prune = false; m_daemon_rpc_mutex.lock(); bool ok = net_utils::invoke_http_json("/gettransactions", req, res, m_http_client); m_daemon_rpc_mutex.unlock(); @@ -8943,6 +8982,8 @@ bool wallet2::check_reserve_proof(const cryptonote::account_public_address &addr COMMAND_RPC_GET_TRANSACTIONS::response gettx_res; for (size_t i = 0; i < proofs.size(); ++i) gettx_req.txs_hashes.push_back(epee::string_tools::pod_to_hex(proofs[i].txid)); + gettx_req.decode_as_json = false; + gettx_req.prune = false; m_daemon_rpc_mutex.lock(); bool ok = net_utils::invoke_http_json("/gettransactions", gettx_req, gettx_res, m_http_client); m_daemon_rpc_mutex.unlock(); @@ -9517,6 +9558,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag COMMAND_RPC_GET_TRANSACTIONS::request gettxs_req; COMMAND_RPC_GET_TRANSACTIONS::response gettxs_res; gettxs_req.decode_as_json = false; + gettxs_req.prune = false; for (const crypto::hash& spent_txid : spent_txids) gettxs_req.txs_hashes.push_back(epee::string_tools::pod_to_hex(spent_txid)); m_daemon_rpc_mutex.lock(); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index ca8bee965..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); @@ -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; |