aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--README.md5
-rw-r--r--contrib/epee/src/string_tools.cpp1
-rw-r--r--src/cryptonote_basic/cryptonote_basic.h32
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp79
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.h3
-rw-r--r--src/cryptonote_basic/miner.cpp2
-rw-r--r--src/cryptonote_core/blockchain.cpp2
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp8
-rw-r--r--src/cryptonote_core/cryptonote_core.h7
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp6
-rw-r--r--src/cryptonote_core/tx_pool.cpp72
-rw-r--r--src/cryptonote_core/tx_pool.h7
-rw-r--r--src/daemon/executor.cpp7
-rw-r--r--src/daemon/executor.h4
-rw-r--r--src/daemon/rpc_command_executor.cpp89
-rw-r--r--src/daemonizer/posix_daemonizer.inl9
-rw-r--r--src/ringct/rctOps.cpp24
-rw-r--r--src/rpc/core_rpc_server.cpp8
-rw-r--r--src/rpc/core_rpc_server.h2
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h22
-rw-r--r--src/simplewallet/simplewallet.cpp20
-rw-r--r--src/wallet/api/wallet_manager.cpp2
-rw-r--r--src/wallet/wallet2.cpp200
-rw-r--r--src/wallet/wallet2.h9
-rw-r--r--tests/unit_tests/serialization.cpp14
26 files changed, 464 insertions, 172 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8fbceeeb5..81b25e5c4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -559,7 +559,7 @@ else()
endif()
if(NOT DEFINED USE_LTO_DEFAULT)
- set(USE_LTO_DEFAULT true)
+ set(USE_LTO_DEFAULT false)
endif()
set(USE_LTO ${USE_LTO_DEFAULT} CACHE BOOL "Use Link-Time Optimization (Release mode only)")
diff --git a/README.md b/README.md
index 24bae84fc..7bebbbc5b 100644
--- a/README.md
+++ b/README.md
@@ -89,8 +89,9 @@ Dates are provided in the format YYYY-MM-DD.
| Fork Date | Consensus version | Minimum Monero Version | Recommended Monero Version | Details |
| ----------------- | ----------------- | ---------------------- | -------------------------- | ------------------ |
| 2016-09-21 | v3 | v0.9.4 | v0.10.0 | Splits coinbase into denominations |
-| 2017-01-05 | v4 | v0.10.1 | v0.10.2.2 | Allow normal and RingCT transactions |
-| 2017-09-21 | v5 | Not determined as of 2017-03-06 | Not determined as of 2017-03-06 | Allow only RingCT transactions |
+| 2017-01-05 | v4 | v0.10.1 | v0.10.2.1 | Allow normal and RingCT transactions |
+| 2017-04-15 | v5 | v0.10.2.1 | v0.10.3 | Adjusted minimum blocksize and fee algorithm |
+| 2017-09-21 | v6 | Not determined as of 2017-03-06 | Not determined as of 2017-03-06 | Allow only RingCT transactions |
## Installing Monero from a Package
diff --git a/contrib/epee/src/string_tools.cpp b/contrib/epee/src/string_tools.cpp
index c861cb1d6..d04b16b75 100644
--- a/contrib/epee/src/string_tools.cpp
+++ b/contrib/epee/src/string_tools.cpp
@@ -30,6 +30,7 @@
# include <winsock2.h>
#else
# include <arpa/inet.h>
+# include <netinet/in.h>
#endif
namespace epee
diff --git a/src/cryptonote_basic/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h
index ed2787cf7..3492ace2b 100644
--- a/src/cryptonote_basic/cryptonote_basic.h
+++ b/src/cryptonote_basic/cryptonote_basic.h
@@ -190,11 +190,24 @@ namespace cryptonote
std::vector<std::vector<crypto::signature> > signatures; //count signatures always the same as inputs count
rct::rctSig rct_signatures;
+ // hash cash
+ mutable crypto::hash hash;
+ mutable size_t blob_size;
+ mutable bool hash_valid;
+ mutable bool blob_size_valid;
+
transaction();
virtual ~transaction();
void set_null();
+ void invalidate_hashes();
BEGIN_SERIALIZE_OBJECT()
+ if (!typename Archive<W>::is_saving())
+ {
+ hash_valid = false;
+ blob_size_valid = false;
+ }
+
FIELDS(*static_cast<transaction_prefix *>(this))
if (version == 1)
@@ -299,6 +312,15 @@ namespace cryptonote
extra.clear();
signatures.clear();
rct_signatures.type = rct::RCTTypeNull;
+ hash_valid = false;
+ blob_size_valid = false;
+ }
+
+ inline
+ void transaction::invalidate_hashes()
+ {
+ hash_valid = false;
+ blob_size_valid = false;
}
inline
@@ -339,10 +361,20 @@ namespace cryptonote
struct block: public block_header
{
+ block(): block_header(), hash_valid(false) {}
+ void invalidate_hashes() { hash_valid = false; }
+
transaction miner_tx;
std::vector<crypto::hash> tx_hashes;
+ // hash cash
+ mutable crypto::hash hash;
+ mutable bool hash_valid;
+
BEGIN_SERIALIZE_OBJECT()
+ if (!typename Archive<W>::is_saving())
+ hash_valid = false;
+
FIELDS(*static_cast<block_header *>(this))
FIELD(miner_tx)
FIELD(tx_hashes)
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 00e7b9d80..2f23194c8 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -43,6 +43,8 @@ using namespace epee;
#define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
+// #define ENABLE_HASH_CASH_INTEGRITY_CHECK
+
static const uint64_t valid_decomposed_outputs[] = {
(uint64_t)1, (uint64_t)2, (uint64_t)3, (uint64_t)4, (uint64_t)5, (uint64_t)6, (uint64_t)7, (uint64_t)8, (uint64_t)9, // 1 piconero
(uint64_t)10, (uint64_t)20, (uint64_t)30, (uint64_t)40, (uint64_t)50, (uint64_t)60, (uint64_t)70, (uint64_t)80, (uint64_t)90,
@@ -68,6 +70,11 @@ static const uint64_t valid_decomposed_outputs[] = {
static std::atomic<unsigned int> default_decimal_point(CRYPTONOTE_DISPLAY_DECIMAL_POINT);
+static std::atomic<uint64_t> tx_hashes_calculated_count(0);
+static std::atomic<uint64_t> tx_hashes_cached_count(0);
+static std::atomic<uint64_t> block_hashes_calculated_count(0);
+static std::atomic<uint64_t> block_hashes_cached_count(0);
+
namespace cryptonote
{
//---------------------------------------------------------------
@@ -93,6 +100,8 @@ namespace cryptonote
binary_archive<false> ba(ss);
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
+ tx.hash_valid = false;
+ tx.blob_size_valid = false;
return true;
}
//---------------------------------------------------------------
@@ -113,6 +122,8 @@ namespace cryptonote
binary_archive<false> ba(ss);
bool r = ::serialization::serialize(ba, tx);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob");
+ tx.hash_valid = false;
+ tx.blob_size_valid = false;
//TODO: validate tx
get_transaction_hash(tx, tx_hash);
@@ -592,7 +603,7 @@ namespace cryptonote
return get_transaction_hash(t, res, NULL);
}
//---------------------------------------------------------------
- bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
+ bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
{
// v1 transactions hash the entire blob
if (t.version == 1)
@@ -647,6 +658,40 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
+ bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size)
+ {
+ if (t.hash_valid)
+ {
+#ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK
+ CHECK_AND_ASSERT_THROW_MES(!calculate_transaction_hash(t, res, blob_size) || t.hash == res, "tx hash cash integrity failure");
+#endif
+ res = t.hash;
+ if (blob_size)
+ {
+ if (!t.blob_size_valid)
+ {
+ t.blob_size = get_object_blobsize(t);
+ t.blob_size_valid = true;
+ }
+ *blob_size = t.blob_size;
+ }
+ ++tx_hashes_cached_count;
+ return true;
+ }
+ ++tx_hashes_calculated_count;
+ bool ret = calculate_transaction_hash(t, res, blob_size);
+ if (!ret)
+ return false;
+ t.hash = res;
+ t.hash_valid = true;
+ if (blob_size)
+ {
+ t.blob_size = *blob_size;
+ t.blob_size_valid = true;
+ }
+ return true;
+ }
+ //---------------------------------------------------------------
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size)
{
return get_transaction_hash(t, res, &blob_size);
@@ -661,7 +706,7 @@ namespace cryptonote
return blob;
}
//---------------------------------------------------------------
- bool get_block_hash(const block& b, crypto::hash& res)
+ bool calculate_block_hash(const block& b, crypto::hash& res)
{
// EXCEPTION FOR BLOCK 202612
const std::string correct_blob_hash_202612 = "3a8a2b3a29b50fc86ff73dd087ea43c6f0d6b8f936c849194d5c84c737903966";
@@ -688,6 +733,26 @@ namespace cryptonote
return hash_result;
}
//---------------------------------------------------------------
+ bool get_block_hash(const block& b, crypto::hash& res)
+ {
+ if (b.hash_valid)
+ {
+#ifdef ENABLE_HASH_CASH_INTEGRITY_CHECK
+ CHECK_AND_ASSERT_THROW_MES(!calculate_block_hash(b, res) || b.hash == res, "block hash cash integrity failure");
+#endif
+ res = b.hash;
+ ++block_hashes_cached_count;
+ return true;
+ }
+ ++block_hashes_calculated_count;
+ bool ret = calculate_block_hash(b, res);
+ if (!ret)
+ return false;
+ b.hash = res;
+ b.hash_valid = true;
+ return true;
+ }
+ //---------------------------------------------------------------
crypto::hash get_block_hash(const block& b)
{
crypto::hash p = null_hash;
@@ -744,6 +809,9 @@ namespace cryptonote
binary_archive<false> ba(ss);
bool r = ::serialization::serialize(ba, b);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob");
+ b.hash_valid = false;
+ b.miner_tx.hash_valid = false;
+ b.miner_tx.blob_size_valid = false;
return true;
}
//---------------------------------------------------------------
@@ -798,4 +866,11 @@ namespace cryptonote
return std::binary_search(begin, end, amount);
}
//---------------------------------------------------------------
+ void get_hash_stats(uint64_t &tx_hashes_calculated, uint64_t &tx_hashes_cached, uint64_t &block_hashes_calculated, uint64_t & block_hashes_cached)
+ {
+ tx_hashes_calculated = tx_hashes_calculated_count;
+ tx_hashes_cached = tx_hashes_cached_count;
+ block_hashes_calculated = block_hashes_calculated_count;
+ block_hashes_cached = block_hashes_cached_count;
+ }
}
diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h
index 7b09235b8..5c10907fd 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.h
+++ b/src/cryptonote_basic/cryptonote_format_utils.h
@@ -85,7 +85,9 @@ namespace cryptonote
bool get_transaction_hash(const transaction& t, crypto::hash& res);
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t& blob_size);
bool get_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
+ bool calculate_transaction_hash(const transaction& t, crypto::hash& res, size_t* blob_size);
blobdata get_block_hashing_blob(const block& b);
+ bool calculate_block_hash(const block& b, crypto::hash& res);
bool get_block_hash(const block& b, crypto::hash& res);
crypto::hash get_block_hash(const block& b);
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height);
@@ -209,6 +211,7 @@ namespace cryptonote
crypto::hash get_tx_tree_hash(const std::vector<crypto::hash>& tx_hashes);
crypto::hash get_tx_tree_hash(const block& b);
bool is_valid_decomposed_amount(uint64_t amount);
+ void get_hash_stats(uint64_t &tx_hashes_calculated, uint64_t &tx_hashes_cached, uint64_t &block_hashes_calculated, uint64_t & block_hashes_cached);
#define CHECKED_GET_SPECIFIC_VARIANT(variant_var, specific_type, variable_name, fail_return_val) \
CHECK_AND_ASSERT_MES(variant_var.type() == typeid(specific_type), fail_return_val, "wrong variant type: " << variant_var.type().name() << ", expected " << typeid(specific_type).name()); \
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 1725b7541..5a2a0d009 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -355,9 +355,11 @@ namespace cryptonote
if(check_hash(h, diffic))
{
+ bl.hash_valid = false;
return true;
}
}
+ bl.hash_valid = false;
return false;
}
//-----------------------------------------------------------------------------------------------------
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 5f8db45ad..f9a17bcb5 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -2860,7 +2860,7 @@ bool Blockchain::check_fee(size_t blob_size, uint64_t fee) const
needed_fee += (blob_size % 1024) ? 1 : 0;
needed_fee *= fee_per_kb;
- if (fee < needed_fee)
+ if (fee < needed_fee * 0.98) // keep a little buffer on acceptance
{
MERROR_VER("transaction fee is not enough: " << print_money(fee) << ", minimum fee: " << print_money(needed_fee));
return false;
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 1b20776a5..4d4b9d4d2 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1036,7 +1036,13 @@ namespace cryptonote
m_mempool.get_transactions(txs);
return true;
}
- //-----------------------------------------------------------------------------------------------
+ //-----------------------------------------------------------------------------------------------
+ bool core::get_pool_transaction_hashes(std::vector<crypto::hash>& txs) const
+ {
+ m_mempool.get_transaction_hashes(txs);
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------
bool core::get_pool_transaction(const crypto::hash &id, transaction& tx) const
{
return m_mempool.get_transaction(id, tx);
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 02d58691d..24b0f0614 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -397,6 +397,13 @@ namespace cryptonote
bool get_pool_transactions(std::list<transaction>& txs) const;
/**
+ * @copydoc tx_memory_pool::get_transactions
+ *
+ * @note see tx_memory_pool::get_transactions
+ */
+ bool get_pool_transaction_hashes(std::vector<crypto::hash>& txs) const;
+
+ /**
* @copydoc tx_memory_pool::get_transaction
*
* @note see tx_memory_pool::get_transaction
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index 672a763fc..47211ff95 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -132,6 +132,9 @@ namespace cryptonote
//lock
tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
tx.vin.push_back(in);
+
+ tx.hash_valid = tx.blob_size_valid = false;
+
//LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee)
// << "), current_block_size=" << current_block_size << ", already_generated_coins=" << already_generated_coins << ", tx_id=" << get_transaction_hash(tx), LOG_LEVEL_2);
return true;
@@ -451,6 +454,8 @@ namespace cryptonote
MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL);
}
+ tx.hash_valid = tx.blob_size_valid = false;
+
return true;
}
//---------------------------------------------------------------
@@ -487,6 +492,7 @@ namespace cryptonote
bl.timestamp = 0;
bl.nonce = nonce;
miner::find_nonce_for_given_block(bl, 1, 0);
+ bl.hash_valid = false;
return true;
}
//---------------------------------------------------------------
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 4dd2832ac..da5e6636a 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -423,6 +423,13 @@ namespace cryptonote
txs.push_back(tx_vt.second.tx);
}
//------------------------------------------------------------------
+ void tx_memory_pool::get_transaction_hashes(std::vector<crypto::hash>& txs) const
+ {
+ CRITICAL_REGION_LOCAL(m_transactions_lock);
+ for(const auto& tx_vt: m_transactions)
+ txs.push_back(get_transaction_hash(tx_vt.second.tx));
+ }
+ //------------------------------------------------------------------
//TODO: investigate whether boolean return is appropriate
bool tx_memory_pool::get_transactions_and_spent_keys_info(std::vector<tx_info>& tx_infos, std::vector<spent_key_image_info>& key_image_infos) const
{
@@ -614,7 +621,7 @@ namespace cryptonote
CRITICAL_REGION_LOCAL(m_transactions_lock);
- uint64_t best_coinbase = 0;
+ uint64_t best_coinbase = 0, coinbase = 0;
total_size = 0;
fee = 0;
@@ -622,11 +629,9 @@ namespace cryptonote
get_block_reward(median_size, total_size, already_generated_coins, best_coinbase, version);
-#if 1
- size_t max_total_size = (130 * median_size) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
-#else
- size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
-#endif
+ size_t max_total_size_pre_v5 = (130 * median_size) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+ size_t max_total_size_v5 = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
+ size_t max_total_size = version >= 5 ? max_total_size_v5 : max_total_size_pre_v5;
std::unordered_set<crypto::key_image> k_images;
LOG_PRINT_L2("Filling block template, median size " << median_size << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool");
@@ -644,21 +649,35 @@ namespace cryptonote
continue;
}
- // If we're getting lower coinbase tx,
- // stop including more tx
- uint64_t block_reward;
- if(!get_block_reward(median_size, total_size + tx_it->second.blob_size, already_generated_coins, block_reward, version))
+ // start using the optimal filling algorithm from v5
+ if (version >= 5)
{
- LOG_PRINT_L2(" would exceed maximum block size");
- sorted_it++;
- continue;
+ // If we're getting lower coinbase tx,
+ // stop including more tx
+ uint64_t block_reward;
+ if(!get_block_reward(median_size, total_size + tx_it->second.blob_size, already_generated_coins, block_reward, version))
+ {
+ LOG_PRINT_L2(" would exceed maximum block size");
+ sorted_it++;
+ continue;
+ }
+ coinbase = block_reward + fee + tx_it->second.fee;
+ if (coinbase < template_accept_threshold(best_coinbase))
+ {
+ LOG_PRINT_L2(" would decrease coinbase to " << print_money(coinbase));
+ sorted_it++;
+ continue;
+ }
}
- uint64_t coinbase = block_reward + fee + tx_it->second.fee;
- if (coinbase < template_accept_threshold(best_coinbase))
+ else
{
- LOG_PRINT_L2(" would decrease coinbase to " << print_money(coinbase));
- sorted_it++;
- continue;
+ // If we've exceeded the penalty free size,
+ // stop including more tx
+ if (total_size > median_size)
+ {
+ LOG_PRINT_L2(" would exceed median block size");
+ break;
+ }
}
// Skip transactions that are not ready to be
@@ -680,9 +699,7 @@ namespace cryptonote
bl.tx_hashes.push_back(tx_it->first);
total_size += tx_it->second.blob_size;
fee += tx_it->second.fee;
-#if 0
best_coinbase = coinbase;
-#endif
append_key_images(k_images, tx_it->second.tx);
sorted_it++;
LOG_PRINT_L2(" added, new block size " << total_size << "/" << max_total_size << ", coinbase " << print_money(best_coinbase));
@@ -700,13 +717,22 @@ namespace cryptonote
size_t n_removed = 0;
size_t tx_size_limit = get_transaction_size_limit(version);
for (auto it = m_transactions.begin(); it != m_transactions.end(); ) {
+ bool remove = false;
+ const crypto::hash &txid = get_transaction_hash(it->second.tx);
if (it->second.blob_size >= tx_size_limit) {
- LOG_PRINT_L1("Transaction " << get_transaction_hash(it->second.tx) << " is too big (" << it->second.blob_size << " bytes), removing it from pool");
+ LOG_PRINT_L1("Transaction " << txid << " is too big (" << it->second.blob_size << " bytes), removing it from pool");
+ remove = true;
+ }
+ else if (m_blockchain.have_tx(txid)) {
+ LOG_PRINT_L1("Transaction " << txid << " is in the blockchain, removing it from pool");
+ remove = true;
+ }
+ if (remove) {
remove_transaction_keyimages(it->second.tx);
- auto sorted_it = find_tx_in_sorted_container(it->first);
+ auto sorted_it = find_tx_in_sorted_container(txid);
if (sorted_it == m_txs_by_fee_and_receive_time.end())
{
- LOG_PRINT_L1("Removing tx " << it->first << " from tx pool, but it was not found in the sorted txs container!");
+ LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!");
}
else
{
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index d71032943..d19f83b2e 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -234,6 +234,13 @@ namespace cryptonote
void get_transactions(std::list<transaction>& txs) const;
/**
+ * @brief get a list of all transaction hashes in the pool
+ *
+ * @param txs return-by-reference the list of transactions
+ */
+ void get_transaction_hashes(std::vector<crypto::hash>& txs) const;
+
+ /**
* @brief get information about all transactions and key images in the pool
*
* see documentation on tx_info and spent_key_image_info for more details
diff --git a/src/daemon/executor.cpp b/src/daemon/executor.cpp
index 53e1c7647..6130bfa28 100644
--- a/src/daemon/executor.cpp
+++ b/src/daemon/executor.cpp
@@ -63,6 +63,13 @@ namespace daemonize
return t_daemon{vm};
}
+ bool t_executor::run_non_interactive(
+ boost::program_options::variables_map const & vm
+ )
+ {
+ return t_daemon{vm}.run(false);
+ }
+
bool t_executor::run_interactive(
boost::program_options::variables_map const & vm
)
diff --git a/src/daemon/executor.h b/src/daemon/executor.h
index b36c819ea..137e7209c 100644
--- a/src/daemon/executor.h
+++ b/src/daemon/executor.h
@@ -56,6 +56,10 @@ namespace daemonize
boost::program_options::variables_map const & vm
);
+ bool run_non_interactive(
+ boost::program_options::variables_map const & vm
+ );
+
bool run_interactive(
boost::program_options::variables_map const & vm
);
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index b145310de..c5b17268d 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -91,6 +91,13 @@ namespace {
s = boost::lexical_cast<std::string>(dt/(3600*24)) + " days";
return s + " " + (t > now ? "in the future" : "ago");
}
+
+ std::string make_error(const std::string &base, const std::string &status)
+ {
+ if (status == CORE_RPC_STATUS_OK)
+ return base;
+ return base + " -- " + status;
+ }
}
t_rpc_command_executor::t_rpc_command_executor(
@@ -207,7 +214,7 @@ bool t_rpc_command_executor::save_blockchain() {
{
if (!m_rpc_server->on_save_bc(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -235,7 +242,7 @@ bool t_rpc_command_executor::show_hash_rate() {
{
if (!m_rpc_server->on_set_log_hash_rate(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
}
}
@@ -262,7 +269,7 @@ bool t_rpc_command_executor::hide_hash_rate() {
{
if (!m_rpc_server->on_set_log_hash_rate(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -289,7 +296,7 @@ bool t_rpc_command_executor::show_difficulty() {
{
if (!m_rpc_server->on_get_info(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message.c_str(), res.status);
return true;
}
}
@@ -373,12 +380,12 @@ bool t_rpc_command_executor::show_status() {
{
if (!m_rpc_server->on_get_info(ireq, ires) || ires.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, ires.status);
return true;
}
if (!m_rpc_server->on_hard_fork_info(hfreq, hfres, error_resp) || hfres.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, hfres.status);
return true;
}
if (!m_rpc_server->on_mining_status(mreq, mres))
@@ -393,7 +400,7 @@ bool t_rpc_command_executor::show_status() {
}
else if (mres.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, mres.status);
return true;
}
}
@@ -439,7 +446,7 @@ bool t_rpc_command_executor::print_connections() {
{
if (!m_rpc_server->on_get_connections(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -504,7 +511,7 @@ bool t_rpc_command_executor::print_blockchain_info(uint64_t start_block_index, u
{
if (!m_rpc_server->on_get_block_headers_range(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -544,7 +551,7 @@ bool t_rpc_command_executor::set_log_level(int8_t level) {
{
if (!m_rpc_server->on_set_log_level(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -572,7 +579,7 @@ bool t_rpc_command_executor::set_log_categories(const std::string &categories) {
{
if (!m_rpc_server->on_set_log_categories(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -599,7 +606,7 @@ bool t_rpc_command_executor::print_height() {
{
if (!m_rpc_server->on_get_height(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -629,7 +636,7 @@ bool t_rpc_command_executor::print_block_by_hash(crypto::hash block_hash) {
{
if (!m_rpc_server->on_get_block(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -660,7 +667,7 @@ bool t_rpc_command_executor::print_block_by_height(uint64_t height) {
{
if (!m_rpc_server->on_get_block(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -689,7 +696,7 @@ bool t_rpc_command_executor::print_transaction(crypto::hash transaction_hash) {
{
if (!m_rpc_server->on_get_transactions(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -752,7 +759,7 @@ bool t_rpc_command_executor::is_key_image_spent(const crypto::key_image &ki) {
{
if (!m_rpc_server->on_is_key_image_spent(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -787,7 +794,7 @@ bool t_rpc_command_executor::print_transaction_pool_long() {
{
if (!m_rpc_server->on_get_transaction_pool(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -870,7 +877,7 @@ bool t_rpc_command_executor::print_transaction_pool_short() {
{
if (!m_rpc_server->on_get_transaction_pool(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -918,7 +925,7 @@ bool t_rpc_command_executor::print_transaction_pool_stats() {
{
if (!m_rpc_server->on_get_transaction_pool(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -978,7 +985,7 @@ bool t_rpc_command_executor::start_mining(cryptonote::account_public_address add
{
if (!m_rpc_server->on_start_mining(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1003,7 +1010,7 @@ bool t_rpc_command_executor::stop_mining() {
{
if (!m_rpc_server->on_stop_mining(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1044,7 +1051,7 @@ bool t_rpc_command_executor::stop_daemon()
{
if (!m_rpc_server->on_stop_daemon(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1142,7 +1149,7 @@ bool t_rpc_command_executor::out_peers(uint64_t limit)
{
if (!m_rpc_server->on_out_peers(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1170,7 +1177,7 @@ bool t_rpc_command_executor::start_save_graph()
{
if (!m_rpc_server->on_start_save_graph(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1196,7 +1203,7 @@ bool t_rpc_command_executor::stop_save_graph()
{
if (!m_rpc_server->on_stop_save_graph(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1223,7 +1230,7 @@ bool t_rpc_command_executor::hard_fork_info(uint8_t version)
{
if (!m_rpc_server->on_hard_fork_info(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1254,7 +1261,7 @@ bool t_rpc_command_executor::print_bans()
{
if (!m_rpc_server->on_get_bans(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1296,7 +1303,7 @@ bool t_rpc_command_executor::ban(const std::string &ip, time_t seconds)
{
if (!m_rpc_server->on_set_bans(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1332,7 +1339,7 @@ bool t_rpc_command_executor::unban(const std::string &ip)
{
if (!m_rpc_server->on_set_bans(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1359,9 +1366,9 @@ bool t_rpc_command_executor::flush_txpool(const std::string &txid)
}
else
{
- if (!m_rpc_server->on_flush_txpool(req, res, error_resp))
+ if (!m_rpc_server->on_flush_txpool(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1390,9 +1397,9 @@ bool t_rpc_command_executor::output_histogram(uint64_t min_count, uint64_t max_c
}
else
{
- if (!m_rpc_server->on_get_output_histogram(req, res, error_resp))
+ if (!m_rpc_server->on_get_output_histogram(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1427,9 +1434,9 @@ bool t_rpc_command_executor::print_coinbase_tx_sum(uint64_t height, uint64_t cou
}
else
{
- if (!m_rpc_server->on_get_coinbase_tx_sum(req, res, error_resp))
+ if (!m_rpc_server->on_get_coinbase_tx_sum(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1467,12 +1474,12 @@ bool t_rpc_command_executor::alt_chain_info()
{
if (!m_rpc_server->on_get_info(ireq, ires) || ires.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, ires.status);
return true;
}
if (!m_rpc_server->on_get_alternate_chains(req, res, error_resp))
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
@@ -1515,12 +1522,12 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks)
{
if (!m_rpc_server->on_get_info(ireq, ires) || ires.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, ires.status);
return true;
}
if (!m_rpc_server->on_get_per_kb_fee_estimate(fereq, feres, error_resp) || feres.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, feres.status);
return true;
}
}
@@ -1546,7 +1553,7 @@ bool t_rpc_command_executor::print_blockchain_dynamic_stats(uint64_t nblocks)
{
if (!m_rpc_server->on_get_block_headers_range(bhreq, bhres, error_resp) || bhres.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, bhres.status);
return true;
}
}
@@ -1612,7 +1619,7 @@ bool t_rpc_command_executor::update(const std::string &command)
{
if (!m_rpc_server->on_update(req, res) || res.status != CORE_RPC_STATUS_OK)
{
- tools::fail_msg_writer() << fail_message.c_str();
+ tools::fail_msg_writer() << make_error(fail_message, res.status);
return true;
}
}
diff --git a/src/daemonizer/posix_daemonizer.inl b/src/daemonizer/posix_daemonizer.inl
index 6ddaacc9d..f8be15dda 100644
--- a/src/daemonizer/posix_daemonizer.inl
+++ b/src/daemonizer/posix_daemonizer.inl
@@ -43,6 +43,10 @@ namespace daemonizer
"detach"
, "Run as daemon"
};
+ const command_line::arg_descriptor<bool> arg_non_interactive = {
+ "non-interactive"
+ , "Run non-interactive"
+ };
}
inline void init_options(
@@ -51,6 +55,7 @@ namespace daemonizer
)
{
command_line::add_arg(normal_options, arg_detach);
+ command_line::add_arg(normal_options, arg_non_interactive);
}
inline boost::filesystem::path get_default_data_dir()
@@ -79,6 +84,10 @@ namespace daemonizer
auto daemon = executor.create_daemon(vm);
return daemon.run();
}
+ else if (command_line::has_arg(vm, arg_non_interactive))
+ {
+ return executor.run_non_interactive(vm);
+ }
else
{
//LOG_PRINT_L0("Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL);
diff --git a/src/ringct/rctOps.cpp b/src/ringct/rctOps.cpp
index 0e1715072..d0e0964b6 100644
--- a/src/ringct/rctOps.cpp
+++ b/src/ringct/rctOps.cpp
@@ -36,6 +36,8 @@ using namespace std;
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "ringct"
+#define CHECK_AND_ASSERT_THROW_MES_L1(expr, message) {if(!(expr)) {MWARNING(message); throw std::runtime_error(message);}}
+
namespace rct {
//Various key initialization functions
@@ -175,7 +177,7 @@ namespace rct {
void scalarmultKey(key & aP, const key &P, const key &a) {
ge_p3 A;
ge_p2 R;
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A, P.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A, P.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
ge_scalarmult(&R, a.bytes, &A);
ge_tobytes(aP.bytes, &R);
}
@@ -184,7 +186,7 @@ namespace rct {
key scalarmultKey(const key & P, const key & a) {
ge_p3 A;
ge_p2 R;
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A, P.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A, P.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
ge_scalarmult(&R, a.bytes, &A);
key aP;
ge_tobytes(aP.bytes, &R);
@@ -196,7 +198,7 @@ namespace rct {
key scalarmultH(const key & a) {
ge_p3 A;
ge_p2 R;
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A, H.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A, H.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
ge_scalarmult(&R, a.bytes, &A);
key aP;
ge_tobytes(aP.bytes, &R);
@@ -208,8 +210,8 @@ namespace rct {
//for curve points: AB = A + B
void addKeys(key &AB, const key &A, const key &B) {
ge_p3 B2, A2;
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
ge_cached tmp2;
ge_p3_to_cached(&tmp2, &B2);
ge_p1p1 tmp3;
@@ -231,7 +233,7 @@ namespace rct {
void addKeys2(key &aGbB, const key &a, const key &b, const key & B) {
ge_p2 rv;
ge_p3 B2;
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
ge_double_scalarmult_base_vartime(&rv, b.bytes, &B2, a.bytes);
ge_tobytes(aGbB.bytes, &rv);
}
@@ -240,7 +242,7 @@ namespace rct {
// input B a curve point and output a ge_dsmp which has precomputation applied
void precomp(ge_dsmp rv, const key & B) {
ge_p3 B2;
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
ge_dsm_precomp(rv, &B2);
}
@@ -250,7 +252,7 @@ namespace rct {
void addKeys3(key &aAbB, const key &a, const key &A, const key &b, const ge_dsmp B) {
ge_p2 rv;
ge_p3 A2;
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
ge_double_scalarmult_precomp_vartime(&rv, a.bytes, &A2, b.bytes, B);
ge_tobytes(aAbB.bytes, &rv);
}
@@ -260,8 +262,8 @@ namespace rct {
//AB = A - B where A, B are curve points
void subKeys(key & AB, const key &A, const key &B) {
ge_p3 B2, A2;
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&B2, B.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&A2, A.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
ge_cached tmp2;
ge_p3_to_cached(&tmp2, &B2);
ge_p1p1 tmp3;
@@ -381,7 +383,7 @@ namespace rct {
ge_p2 point;
ge_p3 res;
key h = cn_fast_hash(hh);
- CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&res, h.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
+ CHECK_AND_ASSERT_THROW_MES_L1(ge_frombytes_vartime(&res, h.bytes) == 0, "ge_frombytes_vartime failed at "+boost::lexical_cast<std::string>(__LINE__));
ge_p3_to_p2(&point, &res);
ge_mul8(&point2, &point);
ge_p1p1_to_p3(&res, &point2);
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 9f7e8aa38..a800dbb35 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -789,6 +789,14 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool core_rpc_server::on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res)
+ {
+ CHECK_CORE_BUSY();
+ m_core.get_pool_transaction_hashes(res.tx_hashes);
+ res.status = CORE_RPC_STATUS_OK;
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res)
{
// FIXME: replace back to original m_p2p.send_stop_signal() after
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 900f473a9..f8eff5f8c 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -92,6 +92,7 @@ namespace cryptonote
MAP_URI_AUTO_JON2_IF("/set_log_level", on_set_log_level, COMMAND_RPC_SET_LOG_LEVEL, !m_restricted)
MAP_URI_AUTO_JON2_IF("/set_log_categories", on_set_log_categories, COMMAND_RPC_SET_LOG_CATEGORIES, !m_restricted)
MAP_URI_AUTO_JON2("/get_transaction_pool", on_get_transaction_pool, COMMAND_RPC_GET_TRANSACTION_POOL)
+ MAP_URI_AUTO_JON2("/get_transaction_pool_hashes.bin", on_get_transaction_pool_hashes, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES)
MAP_URI_AUTO_JON2_IF("/stop_daemon", on_stop_daemon, COMMAND_RPC_STOP_DAEMON, !m_restricted)
MAP_URI_AUTO_JON2("/getinfo", on_get_info, COMMAND_RPC_GET_INFO)
MAP_URI_AUTO_JON2_IF("/out_peers", on_out_peers, COMMAND_RPC_OUT_PEERS, !m_restricted)
@@ -145,6 +146,7 @@ namespace cryptonote
bool on_set_log_level(const COMMAND_RPC_SET_LOG_LEVEL::request& req, COMMAND_RPC_SET_LOG_LEVEL::response& res);
bool on_set_log_categories(const COMMAND_RPC_SET_LOG_CATEGORIES::request& req, COMMAND_RPC_SET_LOG_CATEGORIES::response& res);
bool on_get_transaction_pool(const COMMAND_RPC_GET_TRANSACTION_POOL::request& req, COMMAND_RPC_GET_TRANSACTION_POOL::response& res);
+ bool on_get_transaction_pool_hashes(const COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request& req, COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response& res);
bool on_stop_daemon(const COMMAND_RPC_STOP_DAEMON::request& req, COMMAND_RPC_STOP_DAEMON::response& res);
bool on_out_peers(const COMMAND_RPC_OUT_PEERS::request& req, COMMAND_RPC_OUT_PEERS::response& res);
bool on_start_save_graph(const COMMAND_RPC_START_SAVE_GRAPH::request& req, COMMAND_RPC_START_SAVE_GRAPH::response& res);
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 99aa9815e..6f60093ac 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -49,7 +49,7 @@ namespace cryptonote
// advance which version they will stop working with
// Don't go over 32767 for any of these
#define CORE_RPC_VERSION_MAJOR 1
-#define CORE_RPC_VERSION_MINOR 7
+#define CORE_RPC_VERSION_MINOR 8
#define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor))
#define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR)
@@ -1025,6 +1025,26 @@ namespace cryptonote
};
};
+ struct COMMAND_RPC_GET_TRANSACTION_POOL_HASHES
+ {
+ struct request
+ {
+ BEGIN_KV_SERIALIZE_MAP()
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ std::string status;
+ std::vector<crypto::hash> tx_hashes;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(status)
+ KV_SERIALIZE_CONTAINER_POD_AS_BLOB(tx_hashes)
+ END_KV_SERIALIZE_MAP()
+ };
+ };
+
struct COMMAND_RPC_GET_CONNECTIONS
{
struct request
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 8fcefc06b..6cbdf1a1e 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -637,8 +637,8 @@ simple_wallet::simple_wallet()
m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), tr("incoming_transfers [available|unavailable] - Show incoming transfers, all or filtered by availability"));
m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), tr("payments <PID_1> [<PID_2> ... <PID_N>] - Show payments for given payment ID[s]"));
m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), tr("Show blockchain height"));
- m_cmd_binder.set_handler("transfer_original", boost::bind(&simple_wallet::transfer, this, _1), tr("transfer [<mixin_count>] <addr_1> <amount_1> [<addr_2> <amount_2> ... <addr_N> <amount_N>] [payment_id] - Transfer <amount_1>,... <amount_N> to <address_1>,... <address_N>, respectively. <mixin_count> is the number of extra inputs to include for untraceability (from 2 to maximum available)"));
- m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("Same as transfer_original, but using a new transaction building algorithm"));
+ m_cmd_binder.set_handler("transfer_original", boost::bind(&simple_wallet::transfer, this, _1), tr("Same as transfer, but using an older transaction building algorithm"));
+ m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("transfer [<mixin_count>] <address> <amount> [<payment_id>] - Transfer <amount> to <address>. <mixin_count> is the number of extra inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included)"));
m_cmd_binder.set_handler("locked_transfer", boost::bind(&simple_wallet::locked_transfer, this, _1), tr("locked_transfer [<mixin_count>] <addr> <amount> <lockblocks>(Number of blocks to lock the transaction for, max 1000000) [<payment_id>]"));
m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with mixin 0"));
m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("sweep_all [mixin] address [payment_id] - Send all unlocked balance an address"));
@@ -851,21 +851,7 @@ bool simple_wallet::set_log(const std::vector<std::string> &args)
fail_msg_writer() << tr("usage: set_log <log_level_number_0-4> | <categories>");
return true;
}
- uint16_t l = 0;
- if(epee::string_tools::get_xtype_from_string(l, args[0]))
- {
- if(4 < l)
- {
- fail_msg_writer() << tr("wrong number range, use: set_log <log_level_number_0-4>");
- return true;
- }
-
- mlog_set_log_level(l);
- }
- else
- {
- mlog_set_categories(args.front().c_str());
- }
+ mlog_set_log(args[0].c_str());
return true;
}
//----------------------------------------------------------------------------------------------------
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index ea2a66275..8e86c87b3 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -494,7 +494,7 @@ void WalletManagerFactory::setLogLevel(int level)
void WalletManagerFactory::setLogCategories(const std::string &categories)
{
- mlog_set_categories(categories.c_str());
+ mlog_set_log(categories.c_str());
}
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index dff848a92..b3791b99c 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1381,25 +1381,28 @@ void wallet2::pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_hei
//----------------------------------------------------------------------------------------------------
void wallet2::update_pool_state()
{
+ MDEBUG("update_pool_state start");
+
// get the pool state
- cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::request req;
- cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL::response res;
+ cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::request req;
+ cryptonote::COMMAND_RPC_GET_TRANSACTION_POOL_HASHES::response res;
m_daemon_rpc_mutex.lock();
- bool r = epee::net_utils::invoke_http_json("/get_transaction_pool", req, res, m_http_client, rpc_timeout);
+ bool r = epee::net_utils::invoke_http_json("/get_transaction_pool_hashes.bin", req, res, m_http_client, rpc_timeout);
m_daemon_rpc_mutex.unlock();
- THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool");
- THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_transaction_pool");
+ THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "get_transaction_pool_hashes.bin");
+ THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_transaction_pool_hashes.bin");
THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::get_tx_pool_error);
+ MDEBUG("update_pool_state got pool");
// remove any pending tx that's not in the pool
std::unordered_map<crypto::hash, wallet2::unconfirmed_transfer_details>::iterator it = m_unconfirmed_txs.begin();
while (it != m_unconfirmed_txs.end())
{
- const std::string txid = epee::string_tools::pod_to_hex(it->first);
+ const crypto::hash &txid = it->first;
bool found = false;
- for (auto it2: res.transactions)
+ for (const auto &it2: res.tx_hashes)
{
- if (it2.id_hash == txid)
+ if (it2 == txid)
{
found = true;
break;
@@ -1444,16 +1447,17 @@ void wallet2::update_pool_state()
}
}
}
+ MDEBUG("update_pool_state done first loop");
// remove pool txes to us that aren't in the pool anymore
std::unordered_map<crypto::hash, wallet2::payment_details>::iterator uit = m_unconfirmed_payments.begin();
while (uit != m_unconfirmed_payments.end())
{
- const std::string txid = string_tools::pod_to_hex(uit->first);
+ const crypto::hash &txid = uit->first;
bool found = false;
- for (auto it2: res.transactions)
+ for (const auto &it2: res.tx_hashes)
{
- if (it2.id_hash == txid)
+ if (it2 == txid)
{
found = true;
break;
@@ -1462,102 +1466,122 @@ void wallet2::update_pool_state()
auto pit = uit++;
if (!found)
{
+ MDEBUG("Removing " << txid << " from unconfirmed payments, not found in pool");
m_unconfirmed_payments.erase(pit);
}
}
+ MDEBUG("update_pool_state done second loop");
- // add new pool txes to us
- for (auto it: res.transactions)
+ // gather txids of new pool txes to us
+ std::vector<crypto::hash> txids;
+ for (const auto &txid: res.tx_hashes)
{
- cryptonote::blobdata txid_data;
- if(epee::string_tools::parse_hexstr_to_binbuff(it.id_hash, txid_data) && txid_data.size() == sizeof(crypto::hash))
+ if (m_scanned_pool_txs[0].find(txid) != m_scanned_pool_txs[0].end() || m_scanned_pool_txs[1].find(txid) != m_scanned_pool_txs[1].end())
+ {
+ LOG_PRINT_L2("Already seen " << txid << ", skipped");
+ continue;
+ }
+ if (m_unconfirmed_payments.find(txid) == m_unconfirmed_payments.end())
{
- const crypto::hash txid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
- if (m_unconfirmed_payments.find(txid) == m_unconfirmed_payments.end())
+ LOG_PRINT_L1("Found new pool tx: " << txid);
+ bool found = false;
+ for (const auto &i: m_unconfirmed_txs)
{
- LOG_PRINT_L1("Found new pool tx: " << txid);
- bool found = false;
- for (const auto &i: m_unconfirmed_txs)
+ if (i.first == txid)
{
- if (i.first == txid)
- {
- found = true;
- break;
- }
+ found = true;
+ break;
}
- if (!found)
+ }
+ if (!found)
+ {
+ // not one of those we sent ourselves
+ txids.push_back(txid);
+ }
+ else
+ {
+ LOG_PRINT_L1("We sent that one");
+ }
+ }
+ else
+ {
+ LOG_PRINT_L1("Already saw that one, it's for us");
+ }
+ }
+
+ // get those txes
+ if (!txids.empty())
+ {
+ cryptonote::COMMAND_RPC_GET_TRANSACTIONS::request req;
+ cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res;
+ for (const auto &txid: txids)
+ req.txs_hashes.push_back(epee::string_tools::pod_to_hex(txid));
+ MDEBUG("asking for " << txids.size() << " transactions");
+ req.decode_as_json = 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();
+ MDEBUG("Got " << r << " and " << res.status);
+ if (r && res.status == CORE_RPC_STATUS_OK)
+ {
+ if (res.txs.size() == txids.size())
+ {
+ size_t n = 0;
+ for (const auto &txid: txids)
{
- // not one of those we sent ourselves
- cryptonote::COMMAND_RPC_GET_TRANSACTIONS::request req;
- cryptonote::COMMAND_RPC_GET_TRANSACTIONS::response res;
- req.txs_hashes.push_back(it.id_hash);
- req.decode_as_json = 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();
- if (r && res.status == CORE_RPC_STATUS_OK)
+ // might have just been put in a block
+ if (res.txs[n].in_pool)
{
- if (res.txs.size() == 1)
+ cryptonote::transaction tx;
+ cryptonote::blobdata bd;
+ crypto::hash tx_hash, tx_prefix_hash;
+ if (epee::string_tools::parse_hexstr_to_binbuff(res.txs[n].as_hex, bd))
{
- // might have just been put in a block
- if (res.txs[0].in_pool)
+ if (cryptonote::parse_and_validate_tx_from_blob(bd, tx, tx_hash, tx_prefix_hash))
{
- cryptonote::transaction tx;
- cryptonote::blobdata bd;
- crypto::hash tx_hash, tx_prefix_hash;
- if (epee::string_tools::parse_hexstr_to_binbuff(res.txs[0].as_hex, bd))
+ if (tx_hash == txid)
{
- if (cryptonote::parse_and_validate_tx_from_blob(bd, tx, tx_hash, tx_prefix_hash))
- {
- if (tx_hash == txid)
- {
- process_new_transaction(txid, tx, std::vector<uint64_t>(), 0, time(NULL), false, true);
- }
- else
- {
- LOG_PRINT_L0("Mismatched txids when processing unconfimed txes from pool");
- }
- }
- else
+ process_new_transaction(txid, tx, std::vector<uint64_t>(), 0, time(NULL), false, true);
+ m_scanned_pool_txs[0].insert(txid);
+ if (m_scanned_pool_txs[0].size() > 5000)
{
- LOG_PRINT_L0("failed to validate transaction from daemon");
+ std::swap(m_scanned_pool_txs[0], m_scanned_pool_txs[1]);
+ m_scanned_pool_txs[0].clear();
}
}
else
{
- LOG_PRINT_L0("Failed to parse tx " << txid);
+ LOG_PRINT_L0("Mismatched txids when processing unconfimed txes from pool");
}
}
else
{
- LOG_PRINT_L1("Tx " << txid << " was in pool, but is no more");
+ LOG_PRINT_L0("failed to validate transaction from daemon");
}
}
else
{
- LOG_PRINT_L0("Expected 1 tx, got " << res.txs.size());
+ LOG_PRINT_L0("Failed to parse tx " << txid);
}
}
else
{
- LOG_PRINT_L0("Error calling gettransactions daemon RPC: r " << r << ", status " << res.status);
+ LOG_PRINT_L1("Tx " << txid << " was in pool, but is no more");
}
- }
- else
- {
- LOG_PRINT_L1("We sent that one");
+ ++n;
}
}
else
{
- LOG_PRINT_L1("Already saw that one");
+ LOG_PRINT_L0("Expected " << txids.size() << " tx(es), got " << res.txs.size());
}
}
else
{
- LOG_PRINT_L0("Failed to parse txid");
+ LOG_PRINT_L0("Error calling gettransactions daemon RPC: r " << r << ", status " << res.status);
}
}
+ MDEBUG("update_pool_state end");
}
//----------------------------------------------------------------------------------------------------
void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history)
@@ -3379,7 +3403,7 @@ uint64_t wallet2::get_per_kb_fee()
int wallet2::get_fee_algorithm()
{
// changes at v3 and v5
- if (use_fork_rules(5, -720 * 14))
+ if (use_fork_rules(5, 0))
return 2;
if (use_fork_rules(3, -720 * 14))
return 1;
@@ -4120,7 +4144,7 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money) co
return picks;
}
-static bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices)
+bool wallet2::should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const
{
if (!use_rct)
return false;
@@ -4128,9 +4152,43 @@ static bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const
return false;
if (unused_dust_indices.empty() && unused_transfers_indices.empty())
return false;
+ // we want at least one free rct output to avoid a corner case where
+ // we'd choose a non rct output which doesn't have enough "siblings"
+ // value-wise on the chain, and thus can't be mixed
+ bool found = false;
+ for (auto i: unused_dust_indices)
+ {
+ if (m_transfers[i].is_rct())
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found) for (auto i: unused_transfers_indices)
+ {
+ if (m_transfers[i].is_rct())
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
return true;
}
+std::vector<size_t> wallet2::get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const
+{
+ std::vector<size_t> indices;
+ for (size_t n: unused_dust_indices)
+ if (m_transfers[n].is_rct())
+ indices.push_back(n);
+ for (size_t n: unused_transfers_indices)
+ if (m_transfers[n].is_rct())
+ indices.push_back(n);
+ return indices;
+}
+
// Another implementation of transaction creation that is hopefully better
// While there is anything left to pay, it goes through random outputs and tries
// to fill the next destination/amount. If it fully fills it, it will use the
@@ -4195,8 +4253,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
THROW_WALLET_EXCEPTION_IF(needed_money == 0, error::zero_destination);
// gather all our dust and non dust outputs
- const std::vector<size_t> unused_indices = select_available_outputs_from_histogram(fake_outs_count + 1, true, true, true, trusted_daemon);
- for (size_t i: unused_indices)
+ for (size_t i = 0; i < m_transfers.size(); ++i)
{
const transfer_details& td = m_transfers[i];
if (!td.m_spent && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td))
@@ -4279,7 +4336,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
size_t idx;
if ((dsts.empty() || dsts[0].amount == 0) && !adding_fee) {
// the "make rct txes 2/2" case - we pick a small value output to "clean up" the wallet too
- idx = pop_best_value(unused_dust_indices.empty() ? unused_transfers_indices : unused_dust_indices, tx.selected_transfers, true);
+ std::vector<size_t> indices = get_only_rct(unused_dust_indices, unused_transfers_indices);
+ idx = pop_best_value(indices, tx.selected_transfers, true);
// since we're trying to add a second output which is not strictly needed,
// we only add it if it's unrelated enough to the first one
@@ -4289,6 +4347,8 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
LOG_PRINT_L2("Second outout was not strictly needed, and relatedness " << relatedness << ", not adding");
break;
}
+ pop_if_present(unused_transfers_indices, idx);
+ pop_if_present(unused_dust_indices, idx);
} else if (!prefered_inputs.empty()) {
idx = pop_back(prefered_inputs);
pop_if_present(unused_transfers_indices, idx);
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 5c8d0ae86..565cd9870 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -485,6 +485,10 @@ namespace tools
if(ver < 17)
return;
a & m_unconfirmed_payments;
+ if(ver < 18)
+ return;
+ a & m_scanned_pool_txs[0];
+ a & m_scanned_pool_txs[1];
}
/*!
@@ -633,6 +637,8 @@ namespace tools
void get_outs(std::vector<std::vector<get_outs_entry>> &outs, const std::list<size_t> &selected_transfers, size_t fake_outputs_count);
bool wallet_generate_key_image_helper(const cryptonote::account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, cryptonote::keypair& in_ephemeral, crypto::key_image& ki);
crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const;
+ bool should_pick_a_second_output(bool use_rct, size_t n_transfers, const std::vector<size_t> &unused_transfers_indices, const std::vector<size_t> &unused_dust_indices) const;
+ std::vector<size_t> get_only_rct(const std::vector<size_t> &unused_dust_indices, const std::vector<size_t> &unused_transfers_indices) const;
cryptonote::account_base m_account;
boost::optional<epee::net_utils::http::login> m_daemon_login;
@@ -677,9 +683,10 @@ namespace tools
bool m_confirm_missing_payment_id;
bool m_ask_password;
NodeRPCProxy m_node_rpc_proxy;
+ std::unordered_set<crypto::hash> m_scanned_pool_txs[2];
};
}
-BOOST_CLASS_VERSION(tools::wallet2, 17)
+BOOST_CLASS_VERSION(tools::wallet2, 18)
BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 7)
BOOST_CLASS_VERSION(tools::wallet2::payment_details, 1)
BOOST_CLASS_VERSION(tools::wallet2::unconfirmed_transfer_details, 6)
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index 86e20266b..7afc0d60c 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -331,6 +331,7 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
// Miner tx with empty signatures 2nd vector
tx.signatures.resize(1);
+ tx.invalidate_hashes();
ASSERT_TRUE(serialization::dump_binary(tx, blob));
ASSERT_EQ(7, blob.size()); // 5 bytes + 2 bytes vin[0] + 0 bytes extra + 0 bytes signatures
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
@@ -345,16 +346,19 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
tx.signatures.resize(2);
tx.signatures[0].resize(0);
tx.signatures[1].resize(0);
+ tx.invalidate_hashes();
ASSERT_FALSE(serialization::dump_binary(tx, blob));
// Miner tx with 2 signatures
tx.signatures[0].resize(1);
tx.signatures[1].resize(1);
+ tx.invalidate_hashes();
ASSERT_FALSE(serialization::dump_binary(tx, blob));
// Two txin_gen, no signatures
tx.vin.push_back(txin_gen1);
tx.signatures.resize(0);
+ tx.invalidate_hashes();
ASSERT_TRUE(serialization::dump_binary(tx, blob));
ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
@@ -363,10 +367,12 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
// Two txin_gen, signatures vector contains only one empty element
tx.signatures.resize(1);
+ tx.invalidate_hashes();
ASSERT_FALSE(serialization::dump_binary(tx, blob));
// Two txin_gen, signatures vector contains two empty elements
tx.signatures.resize(2);
+ tx.invalidate_hashes();
ASSERT_TRUE(serialization::dump_binary(tx, blob));
ASSERT_EQ(9, blob.size()); // 5 bytes + 2 * 2 bytes vins + 0 bytes extra + 0 bytes signatures
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
@@ -375,18 +381,21 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
// Two txin_gen, signatures vector contains three empty elements
tx.signatures.resize(3);
+ tx.invalidate_hashes();
ASSERT_FALSE(serialization::dump_binary(tx, blob));
// Two txin_gen, signatures vector contains two non empty elements
tx.signatures.resize(2);
tx.signatures[0].resize(1);
tx.signatures[1].resize(1);
+ tx.invalidate_hashes();
ASSERT_FALSE(serialization::dump_binary(tx, blob));
// A few bytes instead of signature
tx.vin.clear();
tx.vin.push_back(txin_gen1);
tx.signatures.clear();
+ tx.invalidate_hashes();
ASSERT_TRUE(serialization::dump_binary(tx, blob));
blob.append(std::string(sizeof(crypto::signature) / 2, 'x'));
ASSERT_FALSE(serialization::parse_binary(blob, tx1));
@@ -406,6 +415,7 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
tx.vin.push_back(txin_to_key1);
tx.signatures.resize(1);
tx.signatures[0].resize(2);
+ tx.invalidate_hashes();
ASSERT_FALSE(serialization::dump_binary(tx, blob));
// Too much signatures for two inputs
@@ -413,24 +423,28 @@ TEST(Serialization, serializes_transacion_signatures_correctly)
tx.signatures[0].resize(2);
tx.signatures[1].resize(2);
tx.signatures[2].resize(2);
+ tx.invalidate_hashes();
ASSERT_FALSE(serialization::dump_binary(tx, blob));
// First signatures vector contains too little elements
tx.signatures.resize(2);
tx.signatures[0].resize(1);
tx.signatures[1].resize(2);
+ tx.invalidate_hashes();
ASSERT_FALSE(serialization::dump_binary(tx, blob));
// First signatures vector contains too much elements
tx.signatures.resize(2);
tx.signatures[0].resize(3);
tx.signatures[1].resize(2);
+ tx.invalidate_hashes();
ASSERT_FALSE(serialization::dump_binary(tx, blob));
// There are signatures for each input
tx.signatures.resize(2);
tx.signatures[0].resize(2);
tx.signatures[1].resize(2);
+ tx.invalidate_hashes();
ASSERT_TRUE(serialization::dump_binary(tx, blob));
ASSERT_TRUE(serialization::parse_binary(blob, tx1));
ASSERT_EQ(tx, tx1);