aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--contrib/epee/include/int-util.h3
-rw-r--r--contrib/epee/include/net/abstract_tcp_server2.inl8
-rw-r--r--contrib/epee/include/net/levin_protocol_handler_async.h5
-rw-r--r--contrib/epee/src/CMakeLists.txt3
-rw-r--r--contrib/epee/src/int-util.cpp48
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.cpp7
-rw-r--r--src/cryptonote_basic/miner.cpp4
-rw-r--r--src/cryptonote_basic/verification_context.h1
-rw-r--r--src/cryptonote_config.h1
-rw-r--r--src/cryptonote_core/blockchain.cpp65
-rw-r--r--src/cryptonote_core/tx_pool.cpp55
-rw-r--r--src/cryptonote_core/tx_pool.h7
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h1
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl20
-rw-r--r--src/daemon/rpc_command_executor.cpp1
-rw-r--r--src/p2p/net_node.cpp2
-rw-r--r--src/p2p/net_node.h4
-rw-r--r--src/p2p/net_node.inl12
-rw-r--r--src/p2p/net_node_common.h4
-rw-r--r--src/rpc/core_rpc_server.cpp5
-rw-r--r--src/rpc/core_rpc_server.h2
-rw-r--r--src/rpc/rpc_args.cpp6
-rw-r--r--src/rpc/rpc_args.h2
-rw-r--r--src/simplewallet/simplewallet.cpp146
-rw-r--r--src/simplewallet/simplewallet.h4
-rw-r--r--src/wallet/wallet2.cpp77
-rw-r--r--src/wallet/wallet2.h11
-rw-r--r--src/wallet/wallet_rpc_server.cpp41
-rwxr-xr-xtests/functional_tests/cold_signing.py5
-rwxr-xr-xtests/functional_tests/multisig.py2
-rwxr-xr-xtests/functional_tests/transfer.py34
-rw-r--r--tests/unit_tests/CMakeLists.txt2
-rw-r--r--tests/unit_tests/mul_div.cpp116
-rw-r--r--tests/unit_tests/net.cpp9
-rw-r--r--tests/unit_tests/node_server.cpp (renamed from tests/unit_tests/ban.cpp)37
36 files changed, 543 insertions, 209 deletions
diff --git a/README.md b/README.md
index e74a025eb..e465d1ccc 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ Our researchers are available on IRC in [#monero-research-lab on Freenode](https
- You can subscribe to an [announcement listserv](https://lists.getmonero.org) to get critical announcements from the Monero core team. The announcement list can be very helpful for knowing when software updates are needed.
## Translations
-The CLI wallet is available in different languages. If you want to help translate it, see our self-hosted localization platform, Pootle, on [translate.getmonero.org](https://translate.getmonero.org/projects/CLI/). Every translation *must* be uploaded on the platform, pull requests directly editing the code in this repository will be closed. If you need help with Pootle, you can find a guide with screenshots [here](https://github.com/monero-ecosystem/monero-translations/blob/master/pootle.md).
+The CLI wallet is available in different languages. If you want to help translate it, see our self-hosted localization platform, Weblate, on [translate.getmonero.org](https://translate.getmonero.org/projects/CLI/). Every translation *must* be uploaded on the platform, pull requests directly editing the code in this repository will be closed. If you need help with Weblate, you can find a guide with screenshots [here](https://github.com/monero-ecosystem/monero-translations/blob/master/weblate.md).
 
If you need help/support/info about translations, contact the localization workgroup. You can find the complete list of contacts on the repository of the workgroup: [monero-translations](https://github.com/monero-ecosystem/monero-translations#contacts).
diff --git a/contrib/epee/include/int-util.h b/contrib/epee/include/int-util.h
index 8ef5be40a..939c018ea 100644
--- a/contrib/epee/include/int-util.h
+++ b/contrib/epee/include/int-util.h
@@ -129,6 +129,9 @@ static inline uint32_t div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uin
return remainder;
}
+// Long divisor with 2^64 base
+void div128_64(uint64_t dividend_hi, uint64_t dividend_lo, uint64_t divisor, uint64_t* quotient_hi, uint64_t *quotient_lo, uint64_t *remainder_hi, uint64_t *remainder_lo);
+
#define IDENT16(x) ((uint16_t) (x))
#define IDENT32(x) ((uint32_t) (x))
#define IDENT64(x) ((uint64_t) (x))
diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl
index e455d0204..c52535dcd 100644
--- a/contrib/epee/include/net/abstract_tcp_server2.inl
+++ b/contrib/epee/include/net/abstract_tcp_server2.inl
@@ -559,7 +559,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
while (!message.empty()) {
byte_slice chunk = message.take_slice(chunksize_good);
- MDEBUG("chunk_start="<<chunk.data()<<" ptr="<<message_data<<" pos="<<(chunk.data() - message_data));
+ MDEBUG("chunk_start="<<(void*)chunk.data()<<" ptr="<<message_data<<" pos="<<(chunk.data() - message_data));
MDEBUG("part of " << message.size() << ": pos="<<(chunk.data() - message_data) << " len="<<chunk.size());
bool ok = do_send_chunk(std::move(chunk)); // <====== ***
@@ -984,8 +984,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast<std::string>(port), boost::asio::ip::tcp::resolver::query::canonical_name);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
acceptor_.open(endpoint.protocol());
- // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
- acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ acceptor_.set_option(boost::asio::ip::tcp::acceptor::linger(true, 0));
acceptor_.bind(endpoint);
acceptor_.listen();
boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint();
@@ -1019,8 +1018,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::asio::ip::tcp::resolver::query query(address_ipv6, boost::lexical_cast<std::string>(port_ipv6), boost::asio::ip::tcp::resolver::query::canonical_name);
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
acceptor_ipv6.open(endpoint.protocol());
- // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
- acceptor_ipv6.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
+ acceptor_ipv6.set_option(boost::asio::ip::tcp::acceptor::linger(true, 0));
acceptor_ipv6.set_option(boost::asio::ip::v6_only(true));
acceptor_ipv6.bind(endpoint);
acceptor_ipv6.listen();
diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h
index 41f01e9a0..5774c0ba7 100644
--- a/contrib/epee/include/net/levin_protocol_handler_async.h
+++ b/contrib/epee/include/net/levin_protocol_handler_async.h
@@ -272,6 +272,11 @@ public:
bool add_invoke_response_handler(const callback_t &cb, uint64_t timeout, async_protocol_handler& con, int command)
{
CRITICAL_REGION_LOCAL(m_invoke_response_handlers_lock);
+ if (m_protocol_released)
+ {
+ MERROR("Adding response handler to a released object");
+ return false;
+ }
boost::shared_ptr<invoke_response_handler_base> handler(boost::make_shared<anvoke_handler<callback_t>>(cb, timeout, con, command));
m_invoke_response_handlers.push_back(handler);
return handler->is_timer_started();
diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt
index 9b9fa5a47..5201f59c2 100644
--- a/contrib/epee/src/CMakeLists.txt
+++ b/contrib/epee/src/CMakeLists.txt
@@ -27,7 +27,8 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
add_library(epee STATIC byte_slice.cpp hex.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp
- levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp)
+ levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp
+ int-util.cpp)
if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
add_library(epee_readline STATIC readline_buffer.cpp)
diff --git a/contrib/epee/src/int-util.cpp b/contrib/epee/src/int-util.cpp
new file mode 100644
index 000000000..e9d0822e0
--- /dev/null
+++ b/contrib/epee/src/int-util.cpp
@@ -0,0 +1,48 @@
+// Copyright (c) 2019, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <boost/multiprecision/cpp_int.hpp>
+
+void div128_64(uint64_t dividend_hi, uint64_t dividend_lo, uint64_t divisor, uint64_t* quotient_hi, uint64_t *quotient_lo, uint64_t *remainder_hi, uint64_t *remainder_lo)
+{
+ typedef boost::multiprecision::uint128_t uint128_t;
+
+ uint128_t dividend = dividend_hi;
+ dividend <<= 64;
+ dividend |= dividend_lo;
+
+ uint128_t q, r;
+ divide_qr(dividend, uint128_t(divisor), q, r);
+
+ *quotient_hi = ((q >> 64) & 0xffffffffffffffffull).convert_to<uint64_t>();
+ *quotient_lo = (q & 0xffffffffffffffffull).convert_to<uint64_t>();
+ if (remainder_hi)
+ *remainder_hi = ((r >> 64) & 0xffffffffffffffffull).convert_to<uint64_t>();
+ if (remainder_lo)
+ *remainder_lo = (r & 0xffffffffffffffffull).convert_to<uint64_t>();
+}
diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp
index d8de65b81..9bafcfc86 100644
--- a/src/cryptonote_basic/cryptonote_basic_impl.cpp
+++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp
@@ -110,9 +110,6 @@ namespace cryptonote {
return false;
}
- assert(median_weight < std::numeric_limits<uint32_t>::max());
- assert(current_block_weight < std::numeric_limits<uint32_t>::max());
-
uint64_t product_hi;
// BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being
// treated as 32-bit by default.
@@ -122,8 +119,8 @@ namespace cryptonote {
uint64_t reward_hi;
uint64_t reward_lo;
- div128_32(product_hi, product_lo, static_cast<uint32_t>(median_weight), &reward_hi, &reward_lo);
- div128_32(reward_hi, reward_lo, static_cast<uint32_t>(median_weight), &reward_hi, &reward_lo);
+ div128_64(product_hi, product_lo, median_weight, &reward_hi, &reward_lo, NULL, NULL);
+ div128_64(reward_hi, reward_lo, median_weight, &reward_hi, &reward_lo, NULL, NULL);
assert(0 == reward_hi);
assert(reward_lo < base_reward);
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 0188bf114..c4b5c8455 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -62,7 +62,9 @@
#include <devstat.h>
#include <errno.h>
#include <fcntl.h>
+#if defined(__amd64__) || defined(__i386__) || defined(__x86_64__)
#include <machine/apm_bios.h>
+#endif
#include <stdio.h>
#include <sys/resource.h>
#include <sys/sysctl.h>
@@ -1086,6 +1088,7 @@ namespace cryptonote
return boost::logic::tribool(boost::logic::indeterminate);
}
+#if defined(__amd64__) || defined(__i386__) || defined(__x86_64__)
apm_info info;
if( ioctl(fd, APMIO_GETINFO, &info) == -1 ) {
close(fd);
@@ -1126,6 +1129,7 @@ namespace cryptonote
LOG_ERROR("sysctlbyname(\"hw.acpi.acline\") output is unexpectedly "
<< n << " bytes instead of the expected " << sizeof(ac) << " bytes.");
return boost::logic::tribool(boost::logic::indeterminate);
+#endif
}
return boost::logic::tribool(ac == 0);
#endif
diff --git a/src/cryptonote_basic/verification_context.h b/src/cryptonote_basic/verification_context.h
index 3d7200fae..f5f663464 100644
--- a/src/cryptonote_basic/verification_context.h
+++ b/src/cryptonote_basic/verification_context.h
@@ -58,5 +58,6 @@ namespace cryptonote
bool m_marked_as_orphaned;
bool m_already_exists;
bool m_partial_block_reward;
+ bool m_bad_pow; // if bad pow, bad peer outright for DoS protection
};
}
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index 69551934a..86e6c99d1 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -165,6 +165,7 @@
#define HF_VERSION_SAME_MIXIN 12
#define HF_VERSION_REJECT_SIGS_IN_COINBASE 12
#define HF_VERSION_ENFORCE_MIN_AGE 12
+#define HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY 12
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index b672ccd6e..b7e9f4ca2 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -1176,9 +1176,18 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
}
}
- std::vector<uint64_t> last_blocks_weights;
- get_last_n_blocks_weights(last_blocks_weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
- if (!get_block_reward(epee::misc_utils::median(last_blocks_weights), cumulative_block_weight, already_generated_coins, base_reward, version))
+ uint64_t median_weight;
+ if (version >= HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY)
+ {
+ median_weight = m_current_block_cumul_weight_median;
+ }
+ else
+ {
+ std::vector<uint64_t> last_blocks_weights;
+ get_last_n_blocks_weights(last_blocks_weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
+ median_weight = epee::misc_utils::median(last_blocks_weights);
+ }
+ if (!get_block_reward(median_weight, cumulative_block_weight, already_generated_coins, base_reward, version))
{
MERROR_VER("block weight " << cumulative_block_weight << " is bigger than allowed for this blockchain");
return false;
@@ -1694,7 +1703,8 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
// Check the block's hash against the difficulty target for its alt chain
difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
- crypto::hash proof_of_work = null_hash;
+ crypto::hash proof_of_work;
+ memset(proof_of_work.data, 0xff, sizeof(proof_of_work.data));
if (b.major_version >= RX_BLOCK_VERSION)
{
crypto::hash seedhash = null_hash;
@@ -1723,6 +1733,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
{
MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff);
bvc.m_verifivation_failed = true;
+ bvc.m_bad_pow = true;
return false;
}
@@ -1749,6 +1760,34 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
}
bei.cumulative_difficulty += current_diff;
+ bei.block_cumulative_weight = cryptonote::get_transaction_weight(b.miner_tx);
+ for (const crypto::hash &txid: b.tx_hashes)
+ {
+ cryptonote::tx_memory_pool::tx_details td;
+ cryptonote::blobdata blob;
+ if (m_tx_pool.get_transaction_info(txid, td))
+ {
+ bei.block_cumulative_weight += td.weight;
+ }
+ else if (m_db->get_pruned_tx_blob(txid, blob))
+ {
+ cryptonote::transaction tx;
+ if (!cryptonote::parse_and_validate_tx_base_from_blob(blob, tx))
+ {
+ MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) refers to unparsable transaction hash " << txid << ".");
+ bvc.m_verifivation_failed = true;
+ return false;
+ }
+ bei.block_cumulative_weight += cryptonote::get_pruned_transaction_weight(tx);
+ }
+ else
+ {
+ // we can't determine the block weight, set it to 0 and break out of the loop
+ bei.block_cumulative_weight = 0;
+ break;
+ }
+ }
+
// add block to alternate blocks storage,
// as well as the current "alt chain" container
CHECK_AND_ASSERT_MES(!m_db->get_alt_block(id, NULL, NULL), false, "insertion of new alternative block returned as it already exists");
@@ -3318,8 +3357,8 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b
if (version >= HF_VERSION_PER_BYTE_FEE)
{
lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi);
- div128_32(hi, lo, min_block_weight, &hi, &lo);
- div128_32(hi, lo, median_block_weight, &hi, &lo);
+ div128_64(hi, lo, min_block_weight, &hi, &lo, NULL, NULL);
+ div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL);
assert(hi == 0);
lo /= 5;
return lo;
@@ -3329,12 +3368,7 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b
uint64_t unscaled_fee_base = (fee_base * min_block_weight / median_block_weight);
lo = mul128(unscaled_fee_base, block_reward, &hi);
- static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD % 1000000 == 0, "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD must be divisible by 1000000");
- static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000 <= std::numeric_limits<uint32_t>::max(), "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD is too large");
-
- // divide in two steps, since the divisor must be 32 bits, but DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD isn't
- div128_32(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000, &hi, &lo);
- div128_32(hi, lo, 1000000, &hi, &lo);
+ div128_64(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD, &hi, &lo, NULL, NULL);
assert(hi == 0);
// quantize fee up to 8 decimals
@@ -3431,7 +3465,8 @@ uint64_t Blockchain::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const
}
const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
- uint64_t fee = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? m_long_term_effective_median_block_weight : median, version);
+ const uint64_t use_median_value = use_long_term_median_in_fee ? std::min<uint64_t>(median, m_long_term_effective_median_block_weight) : median;
+ const uint64_t fee = get_dynamic_base_fee(base_reward, use_median_value, version);
const bool per_byte = version < HF_VERSION_PER_BYTE_FEE;
MDEBUG("Estimating " << grace_blocks << "-block fee at " << print_money(fee) << "/" << (per_byte ? "byte" : "kB"));
return fee;
@@ -3700,7 +3735,8 @@ leave:
TIME_MEASURE_START(longhash_calculating_time);
- crypto::hash proof_of_work = null_hash;
+ crypto::hash proof_of_work;
+ memset(proof_of_work.data, 0xff, sizeof(proof_of_work.data));
// Formerly the code below contained an if loop with the following condition
// !m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height())
@@ -3749,6 +3785,7 @@ leave:
{
MERROR_VER("Block with id: " << id << std::endl << "does not have enough proof of work: " << proof_of_work << " at height " << blockchain_height << ", unexpected difficulty: " << current_diffic);
bvc.m_verifivation_failed = true;
+ bvc.m_bad_pow = true;
goto leave;
}
}
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 0b7e5c199..648e691d0 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -518,6 +518,59 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------------------------
+ bool tx_memory_pool::get_transaction_info(const crypto::hash &txid, tx_details &td) const
+ {
+ PERF_TIMER(get_transaction_info);
+ CRITICAL_REGION_LOCAL(m_transactions_lock);
+ CRITICAL_REGION_LOCAL1(m_blockchain);
+
+ try
+ {
+ LockedTXN lock(m_blockchain);
+ txpool_tx_meta_t meta;
+ if (!m_blockchain.get_txpool_tx_meta(txid, meta))
+ {
+ MERROR("Failed to find tx in txpool");
+ return false;
+ }
+ cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid);
+ auto ci = m_parsed_tx_cache.find(txid);
+ if (ci != m_parsed_tx_cache.end())
+ {
+ td.tx = ci->second;
+ }
+ else if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(txblob, td.tx) : parse_and_validate_tx_from_blob(txblob, td.tx)))
+ {
+ MERROR("Failed to parse tx from txpool");
+ return false;
+ }
+ else
+ {
+ td.tx.set_hash(txid);
+ }
+ td.blob_size = txblob.size();
+ td.weight = meta.weight;
+ td.fee = meta.fee;
+ td.max_used_block_id = meta.max_used_block_id;
+ td.max_used_block_height = meta.max_used_block_height;
+ td.kept_by_block = meta.kept_by_block;
+ td.last_failed_height = meta.last_failed_height;
+ td.last_failed_id = meta.last_failed_id;
+ td.receive_time = meta.receive_time;
+ td.last_relayed_time = meta.last_relayed_time;
+ td.relayed = meta.relayed;
+ td.do_not_relay = meta.do_not_relay;
+ td.double_spend_seen = meta.double_spend_seen;
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Failed to get tx from txpool: " << e.what());
+ return false;
+ }
+
+ return true;
+ }
+ //---------------------------------------------------------------------------------
void tx_memory_pool::on_idle()
{
m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();});
@@ -911,7 +964,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::check_for_key_images(const std::vector<crypto::key_image>& key_images, std::vector<bool> spent) const
+ bool tx_memory_pool::check_for_key_images(const std::vector<crypto::key_image>& key_images, std::vector<bool>& spent) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 895014d17..dec7e3cd9 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -301,7 +301,7 @@ namespace cryptonote
*
* @return true
*/
- bool check_for_key_images(const std::vector<crypto::key_image>& key_images, std::vector<bool> spent) const;
+ bool check_for_key_images(const std::vector<crypto::key_image>& key_images, std::vector<bool>& spent) const;
/**
* @brief get a specific transaction from the pool
@@ -429,6 +429,11 @@ namespace cryptonote
bool double_spend_seen; //!< true iff another tx was seen double spending this one
};
+ /**
+ * @brief get infornation about a single transaction
+ */
+ bool get_transaction_info(const crypto::hash &txid, tx_details &td) const;
+
private:
/**
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index 2666733da..b16b42564 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -139,6 +139,7 @@ namespace cryptonote
bool should_download_next_span(cryptonote_connection_context& context, bool standby);
bool should_ask_for_pruned_data(cryptonote_connection_context& context, uint64_t first_block_height, uint64_t nblocks, bool check_block_weights) const;
void drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans);
+ void drop_connection_with_score(cryptonote_connection_context &context, unsigned int score, bool flush_all_spans);
bool kick_idle_peers();
bool check_standby_peers();
bool update_sync_search();
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 91bcd86cc..bc5c8d6de 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -477,7 +477,7 @@ namespace cryptonote
if(bvc.m_verifivation_failed)
{
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection");
- drop_connection(context, true, false);
+ drop_connection_with_score(context, bvc.m_bad_pow ? P2P_IP_FAILS_BEFORE_BLOCK : 1, false);
return 1;
}
if(bvc.m_added_to_main_chain)
@@ -751,7 +751,7 @@ namespace cryptonote
if( bvc.m_verifivation_failed )
{
LOG_PRINT_CCONTEXT_L0("Block verification failed, dropping connection");
- drop_connection(context, true, false);
+ drop_connection_with_score(context, bvc.m_bad_pow ? P2P_IP_FAILS_BEFORE_BLOCK : 1, false);
return 1;
}
if( bvc.m_added_to_main_chain )
@@ -1374,7 +1374,7 @@ namespace cryptonote
{
if (!m_p2p->for_connection(span_connection_id, [&](cryptonote_connection_context& context, nodetool::peerid_type peer_id, uint32_t f)->bool{
LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection");
- drop_connection(context, true, true);
+ drop_connection_with_score(context, bvc.m_bad_pow ? P2P_IP_FAILS_BEFORE_BLOCK : 1, true);
return 1;
}))
LOG_ERROR_CCONTEXT("span connection id not found");
@@ -2428,14 +2428,14 @@ skip:
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
- void t_cryptonote_protocol_handler<t_core>::drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans)
+ void t_cryptonote_protocol_handler<t_core>::drop_connection_with_score(cryptonote_connection_context &context, unsigned score, bool flush_all_spans)
{
LOG_DEBUG_CC(context, "dropping connection id " << context.m_connection_id << " (pruning seed " <<
epee::string_tools::to_string_hex(context.m_pruning_seed) <<
- "), add_fail " << add_fail << ", flush_all_spans " << flush_all_spans);
+ "), score " << score << ", flush_all_spans " << flush_all_spans);
- if (add_fail)
- m_p2p->add_host_fail(context.m_remote_address);
+ if (score > 0)
+ m_p2p->add_host_fail(context.m_remote_address, score);
m_block_queue.flush_spans(context.m_connection_id, flush_all_spans);
@@ -2443,6 +2443,12 @@ skip:
}
//------------------------------------------------------------------------------------------------------------------------
template<class t_core>
+ void t_cryptonote_protocol_handler<t_core>::drop_connection(cryptonote_connection_context &context, bool add_fail, bool flush_all_spans)
+ {
+ return drop_connection_with_score(context, add_fail ? 1 : 0, flush_all_spans);
+ }
+ //------------------------------------------------------------------------------------------------------------------------
+ template<class t_core>
void t_cryptonote_protocol_handler<t_core>::on_connection_close(cryptonote_connection_context &context)
{
uint64_t target = 0;
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index 014865730..75c54d048 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -92,6 +92,7 @@ namespace {
<< "depth: " << boost::lexical_cast<std::string>(header.depth) << std::endl
<< "hash: " << header.hash << std::endl
<< "difficulty: " << header.wide_difficulty << std::endl
+ << "cumulative difficulty: " << header.wide_cumulative_difficulty << std::endl
<< "POW hash: " << header.pow_hash << std::endl
<< "block size: " << header.block_size << std::endl
<< "block weight: " << header.block_weight << std::endl
diff --git a/src/p2p/net_node.cpp b/src/p2p/net_node.cpp
index c7fc058ca..ae23bb7fd 100644
--- a/src/p2p/net_node.cpp
+++ b/src/p2p/net_node.cpp
@@ -152,7 +152,7 @@ namespace nodetool
const command_line::arg_descriptor<bool> arg_no_igd = {"no-igd", "Disable UPnP port mapping"};
const command_line::arg_descriptor<std::string> arg_igd = {"igd", "UPnP port mapping (disabled, enabled, delayed)", "delayed"};
const command_line::arg_descriptor<bool> arg_p2p_use_ipv6 = {"p2p-use-ipv6", "Enable IPv6 for p2p", false};
- const command_line::arg_descriptor<bool> arg_p2p_require_ipv4 = {"p2p-require-ipv4", "Require successful IPv4 bind for p2p", true};
+ const command_line::arg_descriptor<bool> arg_p2p_ignore_ipv4 = {"p2p-ignore-ipv4", "Ignore unsuccessful IPv4 bind for p2p", false};
const command_line::arg_descriptor<int64_t> arg_out_peers = {"out-peers", "set max number of out peers", -1};
const command_line::arg_descriptor<int64_t> arg_in_peers = {"in-peers", "set max number of in peers", -1};
const command_line::arg_descriptor<int> arg_tos_flag = {"tos-flag", "set TOS flag", -1};
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index d7e2e91f5..0c9c285e8 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -342,7 +342,7 @@ namespace nodetool
virtual void request_callback(const epee::net_utils::connection_context_base& context);
virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f);
virtual bool for_connection(const boost::uuids::uuid&, std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f);
- virtual bool add_host_fail(const epee::net_utils::network_address &address);
+ virtual bool add_host_fail(const epee::net_utils::network_address &address, unsigned int score = 1);
//----------------- i_connection_filter --------------------------------------------------------
virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address, time_t *t = NULL);
//-----------------------------------------------------------------------------------------------
@@ -510,7 +510,7 @@ namespace nodetool
extern const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port;
extern const command_line::arg_descriptor<std::string, false, true, 2> arg_p2p_bind_port_ipv6;
extern const command_line::arg_descriptor<bool> arg_p2p_use_ipv6;
- extern const command_line::arg_descriptor<bool> arg_p2p_require_ipv4;
+ extern const command_line::arg_descriptor<bool> arg_p2p_ignore_ipv4;
extern const command_line::arg_descriptor<uint32_t> arg_p2p_external_port;
extern const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip;
extern const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer;
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index bb77ea658..5fccdca5a 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -97,7 +97,7 @@ namespace nodetool
command_line::add_arg(desc, arg_p2p_bind_port, false);
command_line::add_arg(desc, arg_p2p_bind_port_ipv6, false);
command_line::add_arg(desc, arg_p2p_use_ipv6);
- command_line::add_arg(desc, arg_p2p_require_ipv4);
+ command_line::add_arg(desc, arg_p2p_ignore_ipv4);
command_line::add_arg(desc, arg_p2p_external_port);
command_line::add_arg(desc, arg_p2p_allow_local_ip);
command_line::add_arg(desc, arg_p2p_add_peer);
@@ -315,13 +315,13 @@ namespace nodetool
}
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::add_host_fail(const epee::net_utils::network_address &address)
+ bool node_server<t_payload_net_handler>::add_host_fail(const epee::net_utils::network_address &address, unsigned int score)
{
if(!address.is_blockable())
return false;
CRITICAL_REGION_LOCAL(m_host_fails_score_lock);
- uint64_t fails = ++m_host_fails_score[address.host_str()];
+ uint64_t fails = m_host_fails_score[address.host_str()] += score;
MDEBUG("Host " << address.host_str() << " fail score=" << fails);
if(fails > P2P_IP_FAILS_BEFORE_BLOCK)
{
@@ -382,7 +382,7 @@ namespace nodetool
}
m_offline = command_line::get_arg(vm, cryptonote::arg_offline);
m_use_ipv6 = command_line::get_arg(vm, arg_p2p_use_ipv6);
- m_require_ipv4 = command_line::get_arg(vm, arg_p2p_require_ipv4);
+ m_require_ipv4 = !command_line::get_arg(vm, arg_p2p_ignore_ipv4);
public_zone.m_notifier = cryptonote::levin::notify{
public_zone.m_net_server.get_io_service(), public_zone.m_net_server.get_config_shared(), nullptr, true
};
@@ -1864,7 +1864,11 @@ namespace nodetool
const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>();
if (ipv4.ip() == 0)
ignore = true;
+ else if (ipv4.port() == be.rpc_port)
+ ignore = true;
}
+ if (be.pruning_seed && (be.pruning_seed < tools::make_pruning_seed(1, CRYPTONOTE_PRUNING_LOG_STRIPES) || be.pruning_seed > tools::make_pruning_seed(1ul << CRYPTONOTE_PRUNING_LOG_STRIPES, CRYPTONOTE_PRUNING_LOG_STRIPES)))
+ ignore = true;
if (ignore)
{
MDEBUG("Ignoring " << be.adr.str());
diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h
index e0046cd86..752873666 100644
--- a/src/p2p/net_node_common.h
+++ b/src/p2p/net_node_common.h
@@ -60,7 +60,7 @@ namespace nodetool
virtual bool unblock_host(const epee::net_utils::network_address &address)=0;
virtual std::map<std::string, time_t> get_blocked_hosts()=0;
virtual std::map<epee::net_utils::ipv4_network_subnet, time_t> get_blocked_subnets()=0;
- virtual bool add_host_fail(const epee::net_utils::network_address &address)=0;
+ virtual bool add_host_fail(const epee::net_utils::network_address &address, unsigned int score = 1)=0;
virtual void add_used_stripe_peer(const t_connection_context &context)=0;
virtual void remove_used_stripe_peer(const t_connection_context &context)=0;
virtual void clear_used_stripe_peers()=0;
@@ -122,7 +122,7 @@ namespace nodetool
{
return std::map<epee::net_utils::ipv4_network_subnet, time_t>();
}
- virtual bool add_host_fail(const epee::net_utils::network_address &address)
+ virtual bool add_host_fail(const epee::net_utils::network_address &address, unsigned int score)
{
return true;
}
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index fef86fd34..dfc4d4cf3 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -217,13 +217,13 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
- bool core_rpc_server::add_host_fail(const connection_context *ctx)
+ bool core_rpc_server::add_host_fail(const connection_context *ctx, unsigned int score)
{
if(!ctx || !ctx->m_remote_address.is_blockable())
return false;
CRITICAL_REGION_LOCAL(m_host_fails_score_lock);
- uint64_t fails = ++m_host_fails_score[ctx->m_remote_address.host_str()];
+ uint64_t fails = m_host_fails_score[ctx->m_remote_address.host_str()] += score;
MDEBUG("Host " << ctx->m_remote_address.host_str() << " fail score=" << fails);
if(fails > RPC_IP_FAILS_BEFORE_BLOCK)
{
@@ -1951,7 +1951,6 @@ namespace cryptonote
error_resp.message = "Internal error: can't produce valid response.";
return false;
}
- res.miner_tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(blk.miner_tx));
for (size_t n = 0; n < blk.tx_hashes.size(); ++n)
{
res.tx_hashes.push_back(epee::string_tools::pod_to_hex(blk.tx_hashes[n]));
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 379f6ed28..fe03012b7 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -241,7 +241,7 @@ namespace cryptonote
private:
bool check_core_busy();
bool check_core_ready();
- bool add_host_fail(const connection_context *ctx);
+ bool add_host_fail(const connection_context *ctx, unsigned int score = 1);
//utils
uint64_t get_block_reward(const block& blk);
diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp
index 68b33cb8c..0eaa0ef0e 100644
--- a/src/rpc/rpc_args.cpp
+++ b/src/rpc/rpc_args.cpp
@@ -92,7 +92,7 @@ namespace cryptonote
: rpc_bind_ip({"rpc-bind-ip", rpc_args::tr("Specify IP to bind RPC server"), "127.0.0.1"})
, rpc_bind_ipv6_address({"rpc-bind-ipv6-address", rpc_args::tr("Specify IPv6 address to bind RPC server"), "::1"})
, rpc_use_ipv6({"rpc-use-ipv6", rpc_args::tr("Allow IPv6 for RPC"), false})
- , rpc_require_ipv4({"rpc-require-ipv4", rpc_args::tr("Require successful IPv4 bind for RPC"), true})
+ , rpc_ignore_ipv4({"rpc-ignore-ipv4", rpc_args::tr("Ignore unsuccessful IPv4 bind for RPC"), false})
, rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true})
, confirm_external_bind({"confirm-external-bind", rpc_args::tr("Confirm rpc-bind-ip value is NOT a loopback (local) IP")})
, rpc_access_control_origins({"rpc-access-control-origins", rpc_args::tr("Specify a comma separated list of origins to allow cross origin resource sharing"), ""})
@@ -113,7 +113,7 @@ namespace cryptonote
command_line::add_arg(desc, arg.rpc_bind_ip);
command_line::add_arg(desc, arg.rpc_bind_ipv6_address);
command_line::add_arg(desc, arg.rpc_use_ipv6);
- command_line::add_arg(desc, arg.rpc_require_ipv4);
+ command_line::add_arg(desc, arg.rpc_ignore_ipv4);
command_line::add_arg(desc, arg.rpc_login);
command_line::add_arg(desc, arg.confirm_external_bind);
command_line::add_arg(desc, arg.rpc_access_control_origins);
@@ -135,7 +135,7 @@ namespace cryptonote
config.bind_ip = command_line::get_arg(vm, arg.rpc_bind_ip);
config.bind_ipv6_address = command_line::get_arg(vm, arg.rpc_bind_ipv6_address);
config.use_ipv6 = command_line::get_arg(vm, arg.rpc_use_ipv6);
- config.require_ipv4 = command_line::get_arg(vm, arg.rpc_require_ipv4);
+ config.require_ipv4 = !command_line::get_arg(vm, arg.rpc_ignore_ipv4);
if (!config.bind_ip.empty())
{
// always parse IP here for error consistency
diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h
index cd154a4d0..bdb9c70d5 100644
--- a/src/rpc/rpc_args.h
+++ b/src/rpc/rpc_args.h
@@ -54,7 +54,7 @@ namespace cryptonote
const command_line::arg_descriptor<std::string> rpc_bind_ip;
const command_line::arg_descriptor<std::string> rpc_bind_ipv6_address;
const command_line::arg_descriptor<bool> rpc_use_ipv6;
- const command_line::arg_descriptor<bool> rpc_require_ipv4;
+ const command_line::arg_descriptor<bool> rpc_ignore_ipv4;
const command_line::arg_descriptor<std::string> rpc_login;
const command_line::arg_descriptor<bool> confirm_external_bind;
const command_line::arg_descriptor<std::string> rpc_access_control_origins;
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index f07d142fb..43fd99304 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -119,12 +119,10 @@ typedef cryptonote::simple_wallet sw;
#define LONG_PAYMENT_ID_SUPPORT_CHECK() \
do { \
- if (!m_long_payment_id_support) { \
- fail_msg_writer() << tr("Warning: Long payment IDs are obsolete."); \
- fail_msg_writer() << tr("Long payment IDs are not encrypted on the blockchain, and will harm your privacy."); \
- fail_msg_writer() << tr("Use --long-payment-id-support-bad-for-privacy if you really must use one, and warn the recipient they are using an obsolete feature that will disappear in the future."); \
- return true; \
- } \
+ fail_msg_writer() << tr("Error: Long payment IDs are obsolete."); \
+ fail_msg_writer() << tr("Long payment IDs were not encrypted on the blockchain and would harm your privacy."); \
+ fail_msg_writer() << tr("If the party you're sending to still requires a long payment ID, please notify them."); \
+ return true; \
} while(0)
enum TransferType {
@@ -155,7 +153,6 @@ namespace
const command_line::arg_descriptor<bool> arg_create_address_file = {"create-address-file", sw::tr("Create an address file for new wallets"), false};
const command_line::arg_descriptor<std::string> arg_subaddress_lookahead = {"subaddress-lookahead", tools::wallet2::tr("Set subaddress lookahead sizes to <major>:<minor>"), ""};
const command_line::arg_descriptor<bool> arg_use_english_language_names = {"use-english-language-names", sw::tr("Display English language names"), false};
- const command_line::arg_descriptor<bool> arg_long_payment_id_support = {"long-payment-id-support-bad-for-privacy", sw::tr("Support obsolete long (unencrypted) payment ids (using them harms your privacy)"), false};
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
@@ -2157,8 +2154,8 @@ bool simple_wallet::welcome(const std::vector<std::string> &args)
message_writer() << tr("Welcome to Monero, the private cryptocurrency.");
message_writer() << "";
message_writer() << tr("Monero, like Bitcoin, is a cryptocurrency. That is, it is digital money.");
- message_writer() << tr("Unlike Bitcoin, your Monero transactions and balance stay private, and not visible to the world by default.");
- message_writer() << tr("However, you have the option of making those available to select parties, if you choose to.");
+ message_writer() << tr("Unlike Bitcoin, your Monero transactions and balance stay private and are not visible to the world by default.");
+ message_writer() << tr("However, you have the option of making those available to select parties if you choose to.");
message_writer() << "";
message_writer() << tr("Monero protects your privacy on the blockchain, and while Monero strives to improve all the time,");
message_writer() << tr("no privacy technology can be 100% perfect, Monero included.");
@@ -2166,7 +2163,7 @@ bool simple_wallet::welcome(const std::vector<std::string> &args)
message_writer() << tr("Flaws in Monero may be discovered in the future, and attacks may be developed to peek under some");
message_writer() << tr("of the layers of privacy Monero provides. Be safe and practice defense in depth.");
message_writer() << "";
- message_writer() << tr("Welcome to Monero and financial privacy. For more information, see https://getmonero.org/");
+ message_writer() << tr("Welcome to Monero and financial privacy. For more information see https://GetMonero.org");
return true;
}
@@ -2406,21 +2403,6 @@ bool simple_wallet::set_refresh_type(const std::vector<std::string> &args/* = st
return true;
}
-bool simple_wallet::set_confirm_missing_payment_id(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
-{
- LONG_PAYMENT_ID_SUPPORT_CHECK();
-
- const auto pwd_container = get_and_verify_password();
- if (pwd_container)
- {
- parse_bool_and_use(args[1], [&](bool r) {
- m_wallet->confirm_missing_payment_id(r);
- m_wallet->rewrite(m_wallet_file, pwd_container->password());
- });
- }
- return true;
-}
-
bool simple_wallet::set_ask_password(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
@@ -2677,6 +2659,43 @@ bool simple_wallet::set_ignore_fractional_outputs(const std::vector<std::string>
return true;
}
+
+bool simple_wallet::set_ignore_outputs_above(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
+{
+ const auto pwd_container = get_and_verify_password();
+ if (pwd_container)
+ {
+ uint64_t amount;
+ if (!cryptonote::parse_amount(amount, args[1]))
+ {
+ fail_msg_writer() << tr("Invalid amount");
+ return true;
+ }
+ if (amount == 0)
+ amount = MONEY_SUPPLY;
+ m_wallet->ignore_outputs_above(amount);
+ m_wallet->rewrite(m_wallet_file, pwd_container->password());
+ }
+ return true;
+}
+
+bool simple_wallet::set_ignore_outputs_below(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
+{
+ const auto pwd_container = get_and_verify_password();
+ if (pwd_container)
+ {
+ uint64_t amount;
+ if (!cryptonote::parse_amount(amount, args[1]))
+ {
+ fail_msg_writer() << tr("Invalid amount");
+ return true;
+ }
+ m_wallet->ignore_outputs_below(amount);
+ m_wallet->rewrite(m_wallet_file, pwd_container->password());
+ }
+ return true;
+}
+
bool simple_wallet::set_track_uses(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
@@ -2991,6 +3010,10 @@ simple_wallet::simple_wallet()
" Set to the height of a key reusing fork you want to use, 0 to use default.\n "
"ignore-fractional-outputs <1|0>\n "
" Whether to ignore fractional outputs that result in net loss when spending due to fee.\n "
+ "ignore-outputs-above <amount>\n "
+ " Ignore outputs of amount above this threshold when spending. Value 0 is translated to the maximum value (18 million) which disables this filter.\n "
+ "ignore-outputs-below <amount>\n "
+ " Ignore outputs of amount below this threshold when spending.\n "
"track-uses <1|0>\n "
" Whether to keep track of owned outputs uses.\n "
"setup-background-mining <1|0>\n "
@@ -3351,7 +3374,6 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "auto-refresh = " << m_wallet->auto_refresh();
success_msg_writer() << "refresh-type = " << get_refresh_type_name(m_wallet->get_refresh_type());
success_msg_writer() << "priority = " << priority<< " (" << priority_string << ")";
- success_msg_writer() << "confirm-missing-payment-id = " << m_wallet->confirm_missing_payment_id();
success_msg_writer() << "ask-password = " << m_wallet->ask_password() << " (" << ask_password_string << ")";
success_msg_writer() << "unit = " << cryptonote::get_unit(cryptonote::get_default_decimal_point());
success_msg_writer() << "min-outputs-count = " << m_wallet->get_min_output_count();
@@ -3368,6 +3390,8 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
success_msg_writer() << "subaddress-lookahead = " << lookahead.first << ":" << lookahead.second;
success_msg_writer() << "segregation-height = " << m_wallet->segregation_height();
success_msg_writer() << "ignore-fractional-outputs = " << m_wallet->ignore_fractional_outputs();
+ success_msg_writer() << "ignore-outputs-above = " << cryptonote::print_money(m_wallet->ignore_outputs_above());
+ success_msg_writer() << "ignore-outputs-below = " << cryptonote::print_money(m_wallet->ignore_outputs_below());
success_msg_writer() << "track-uses = " << m_wallet->track_uses();
success_msg_writer() << "setup-background-mining = " << setup_background_mining_string;
success_msg_writer() << "device-name = " << m_wallet->device_name();
@@ -3416,7 +3440,6 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("auto-refresh", set_auto_refresh, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("refresh-type", set_refresh_type, tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)"));
CHECK_SIMPLE_VARIABLE("priority", set_default_priority, tr("0, 1, 2, 3, or 4, or one of ") << join_priority_strings(", "));
- CHECK_SIMPLE_VARIABLE("confirm-missing-payment-id", set_confirm_missing_payment_id, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("ask-password", set_ask_password, tr("0|1|2 (or never|action|decrypt)"));
CHECK_SIMPLE_VARIABLE("unit", set_unit, tr("monero, millinero, micronero, nanonero, piconero"));
CHECK_SIMPLE_VARIABLE("min-outputs-count", set_min_output_count, tr("unsigned integer"));
@@ -3432,6 +3455,8 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
CHECK_SIMPLE_VARIABLE("subaddress-lookahead", set_subaddress_lookahead, tr("<major>:<minor>"));
CHECK_SIMPLE_VARIABLE("segregation-height", set_segregation_height, tr("unsigned integer"));
CHECK_SIMPLE_VARIABLE("ignore-fractional-outputs", set_ignore_fractional_outputs, tr("0 or 1"));
+ CHECK_SIMPLE_VARIABLE("ignore-outputs-above", set_ignore_outputs_above, tr("amount"));
+ CHECK_SIMPLE_VARIABLE("ignore-outputs-below", set_ignore_outputs_below, tr("amount"));
CHECK_SIMPLE_VARIABLE("track-uses", set_track_uses, tr("0 or 1"));
CHECK_SIMPLE_VARIABLE("inactivity-lock-timeout", set_inactivity_lock_timeout, tr("unsigned integer (seconds, 0 to disable)"));
CHECK_SIMPLE_VARIABLE("setup-background-mining", set_setup_background_mining, tr("1/yes or 0/no"));
@@ -4231,14 +4256,6 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
if (welcome)
message_writer(console_color_yellow, true) << tr("If you are new to Monero, type \"welcome\" for a brief overview.");
- if (m_long_payment_id_support)
- {
- message_writer(console_color_red, false) <<
- tr("WARNING: obsolete long payment IDs are enabled. Sending transactions with those payment IDs are bad for your privacy.");
- message_writer(console_color_red, false) <<
- tr("It is recommended that you do not use them, and ask recipients who ask for one to not endanger your privacy.");
- }
-
m_last_activity_time = time(NULL);
return true;
}
@@ -4272,7 +4289,6 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
m_do_not_relay = command_line::get_arg(vm, arg_do_not_relay);
m_subaddress_lookahead = command_line::get_arg(vm, arg_subaddress_lookahead);
m_use_english_language_names = command_line::get_arg(vm, arg_use_english_language_names);
- m_long_payment_id_support = command_line::get_arg(vm, arg_long_payment_id_support);
m_restoring = !m_generate_from_view_key.empty() ||
!m_generate_from_spend_key.empty() ||
!m_generate_from_keys.empty() ||
@@ -5103,12 +5119,19 @@ void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid,
if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
{
crypto::hash payment_id = crypto::null_hash;
- if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
+ crypto::hash8 payment_id8 = crypto::null_hash8;
+ if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
+ {
+ if (payment_id8 != crypto::null_hash8)
+ message_writer() <<
+ tr("NOTE: this transaction uses an encrypted payment ID: consider using subaddresses instead");
+ }
+ else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
message_writer(console_color_red, false) <<
- (m_long_payment_id_support ? tr("WARNING: this transaction uses an unencrypted payment ID: consider using subaddresses instead.") : tr("WARNING: this transaction uses an unencrypted payment ID: these are obsolete. Support will be withdrawn in the future. Use subaddresses instead."));
+ tr("WARNING: this transaction uses an unencrypted payment ID: these are obsolete and ignored. Use subaddresses instead.");
}
}
- if (unlock_time)
+ if (unlock_time && !cryptonote::is_coinbase(tx))
message_writer() << tr("NOTE: This transaction is locked, see details with: show_transfer ") + epee::string_tools::pod_to_hex(txid);
if (m_auto_refresh_refreshing)
m_cmd_binder.print_prompt();
@@ -6061,20 +6084,6 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
dsts.push_back(de);
}
- // prompt is there is no payment id and confirmation is required
- if (m_long_payment_id_support && !payment_id_seen && m_wallet->confirm_missing_payment_id() && dsts.size() > num_subaddresses)
- {
- std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay?"), true);
- if (std::cin.eof())
- return false;
- if (!command_line::is_yes(accepted))
- {
- fail_msg_writer() << tr("transaction cancelled.");
-
- return false;
- }
- }
-
SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return false;);
try
@@ -6636,20 +6645,6 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vector<st
payment_id_seen = true;
}
- // prompt is there is no payment id and confirmation is required
- if (m_long_payment_id_support && !payment_id_seen && m_wallet->confirm_missing_payment_id() && !info.is_subaddress)
- {
- std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay?"), true);
- if (std::cin.eof())
- return true;
- if (!command_line::is_yes(accepted))
- {
- fail_msg_writer() << tr("transaction cancelled.");
-
- return true;
- }
- }
-
SCOPED_WALLET_UNLOCK();
try
@@ -6908,22 +6903,6 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
payment_id_seen = true;
}
- // prompt if there is no payment id and confirmation is required
- if (m_long_payment_id_support && !payment_id_seen && m_wallet->confirm_missing_payment_id() && !info.is_subaddress)
- {
- std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay?"), true);
- if (std::cin.eof())
- return true;
- if (!command_line::is_yes(accepted))
- {
- fail_msg_writer() << tr("transaction cancelled.");
-
- // would like to return false, because no tx made, but everything else returns true
- // and I don't know what returning false might adversely affect. *sigh*
- return true;
- }
- }
-
SCOPED_WALLET_UNLOCK();
try
@@ -9744,7 +9723,6 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_create_address_file);
command_line::add_arg(desc_params, arg_subaddress_lookahead);
command_line::add_arg(desc_params, arg_use_english_language_names);
- command_line::add_arg(desc_params, arg_long_payment_id_support);
po::positional_options_description positional_options;
positional_options.add(arg_command.name, -1);
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index 22659e99e..47e08ca87 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -144,6 +144,8 @@ namespace cryptonote
bool set_subaddress_lookahead(const std::vector<std::string> &args = std::vector<std::string>());
bool set_segregation_height(const std::vector<std::string> &args = std::vector<std::string>());
bool set_ignore_fractional_outputs(const std::vector<std::string> &args = std::vector<std::string>());
+ bool set_ignore_outputs_above(const std::vector<std::string> &args = std::vector<std::string>());
+ bool set_ignore_outputs_below(const std::vector<std::string> &args = std::vector<std::string>());
bool set_track_uses(const std::vector<std::string> &args = std::vector<std::string>());
bool set_inactivity_lock_timeout(const std::vector<std::string> &args = std::vector<std::string>());
bool set_setup_background_mining(const std::vector<std::string> &args = std::vector<std::string>());
@@ -430,8 +432,6 @@ namespace cryptonote
std::atomic<bool> m_in_manual_refresh;
uint32_t m_current_subaddress_account;
- bool m_long_payment_id_support;
-
std::atomic<time_t> m_last_activity_time;
std::atomic<bool> m_locked;
std::atomic<bool> m_in_command;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 4f7b6bbd3..c7374b896 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -137,6 +137,8 @@ using namespace cryptonote;
#define DEFAULT_INACTIVITY_LOCK_TIMEOUT 90 // a minute and a half
+#define IGNORE_LONG_PAYMENT_ID_FROM_BLOCK_VERSION 12
+
static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
static const std::string MULTISIG_EXTRA_INFO_MAGIC = "MultisigxV1";
@@ -1113,7 +1115,6 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_first_refresh_done(false),
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(AskPasswordToDecrypt),
m_min_output_count(0),
@@ -1127,6 +1128,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended):
m_key_reuse_mitigation2(true),
m_segregation_height(0),
m_ignore_fractional_outputs(true),
+ m_ignore_outputs_above(MONEY_SUPPLY),
+ m_ignore_outputs_below(0),
m_track_uses(false),
m_inactivity_lock_timeout(DEFAULT_INACTIVITY_LOCK_TIMEOUT),
m_setup_background_mining(BackgroundMiningMaybe),
@@ -1793,7 +1796,7 @@ void wallet2::cache_tx_data(const cryptonote::transaction& tx, const crypto::has
}
}
//----------------------------------------------------------------------------------------------------
-void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache)
+void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache)
{
PERF_TIMER(process_new_transaction);
// In this function, tx (probably) only contains the base information
@@ -2285,8 +2288,18 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
{
- LOG_PRINT_L2("Found unencrypted payment ID: " << payment_id);
- MWARNING("Found unencrypted payment ID: these are bad for privacy, consider using subaddresses instead");
+ bool ignore = block_version >= IGNORE_LONG_PAYMENT_ID_FROM_BLOCK_VERSION;
+ if (ignore)
+ {
+ LOG_PRINT_L2("Found unencrypted payment ID in tx " << txid << " (ignored)");
+ MWARNING("Found OBSOLETE AND IGNORED unencrypted payment ID: these are bad for privacy, use subaddresses instead");
+ payment_id = crypto::null_hash;
+ }
+ else
+ {
+ LOG_PRINT_L2("Found unencrypted payment ID: " << payment_id);
+ MWARNING("Found unencrypted payment ID: these are bad for privacy, consider using subaddresses instead");
+ }
}
}
@@ -2422,7 +2435,7 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry
{
TIME_MEASURE_START(miner_tx_handle_time);
if (m_refresh_type != RefreshNoCoinbase)
- process_new_transaction(get_transaction_hash(b.miner_tx), b.miner_tx, parsed_block.o_indices.indices[0].indices, height, b.timestamp, true, false, false, tx_cache_data[tx_cache_data_offset], output_tracker_cache);
+ process_new_transaction(get_transaction_hash(b.miner_tx), b.miner_tx, parsed_block.o_indices.indices[0].indices, height, b.major_version, b.timestamp, true, false, false, tx_cache_data[tx_cache_data_offset], output_tracker_cache);
++tx_cache_data_offset;
TIME_MEASURE_FINISH(miner_tx_handle_time);
@@ -2431,7 +2444,7 @@ void wallet2::process_new_blockchain_entry(const cryptonote::block& b, const cry
THROW_WALLET_EXCEPTION_IF(bche.txs.size() != parsed_block.txes.size(), error::wallet_internal_error, "Wrong amount of transactions for block");
for (size_t idx = 0; idx < b.tx_hashes.size(); ++idx)
{
- process_new_transaction(b.tx_hashes[idx], parsed_block.txes[idx], parsed_block.o_indices.indices[idx+1].indices, height, b.timestamp, false, false, false, tx_cache_data[tx_cache_data_offset++], output_tracker_cache);
+ process_new_transaction(b.tx_hashes[idx], parsed_block.txes[idx], parsed_block.o_indices.indices[idx+1].indices, height, b.major_version, b.timestamp, false, false, false, tx_cache_data[tx_cache_data_offset++], output_tracker_cache);
}
TIME_MEASURE_FINISH(txs_handle_time);
m_last_block_reward = cryptonote::get_outs_money_amount(b.miner_tx);
@@ -2962,7 +2975,7 @@ void wallet2::update_pool_state(bool refreshed)
[tx_hash](const std::pair<crypto::hash, bool> &e) { return e.first == tx_hash; });
if (i != txids.end())
{
- process_new_transaction(tx_hash, tx, std::vector<uint64_t>(), 0, time(NULL), false, true, tx_entry.double_spend_seen, {});
+ process_new_transaction(tx_hash, tx, std::vector<uint64_t>(), 0, 0, time(NULL), false, true, tx_entry.double_spend_seen, {});
m_scanned_pool_txs[0].insert(tx_hash);
if (m_scanned_pool_txs[0].size() > 5000)
{
@@ -3639,9 +3652,6 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
value2.SetUint64(m_refresh_from_block_height);
json.AddMember("refresh_height", value2, json.GetAllocator());
- 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());
@@ -3687,6 +3697,12 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
value2.SetInt(m_ignore_fractional_outputs ? 1 : 0);
json.AddMember("ignore_fractional_outputs", value2, json.GetAllocator());
+ value2.SetUint64(m_ignore_outputs_above);
+ json.AddMember("ignore_outputs_above", value2, json.GetAllocator());
+
+ value2.SetUint64(m_ignore_outputs_below);
+ json.AddMember("ignore_outputs_below", value2, json.GetAllocator());
+
value2.SetInt(m_track_uses ? 1 : 0);
json.AddMember("track_uses", value2, json.GetAllocator());
@@ -3833,7 +3849,6 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_auto_refresh = true;
m_refresh_type = RefreshType::RefreshDefault;
m_refresh_from_block_height = 0;
- m_confirm_missing_payment_id = true;
m_confirm_non_default_ring_size = true;
m_ask_password = AskPasswordToDecrypt;
cryptonote::set_default_decimal_point(CRYPTONOTE_DISPLAY_DECIMAL_POINT);
@@ -3848,6 +3863,8 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_key_reuse_mitigation2 = true;
m_segregation_height = 0;
m_ignore_fractional_outputs = true;
+ m_ignore_outputs_above = MONEY_SUPPLY;
+ m_ignore_outputs_below = 0;
m_track_uses = false;
m_inactivity_lock_timeout = DEFAULT_INACTIVITY_LOCK_TIMEOUT;
m_setup_background_mining = BackgroundMiningMaybe;
@@ -3968,8 +3985,6 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
}
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, refresh_height, uint64_t, Uint64, false, 0);
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, AskPasswordType, Int, false, AskPasswordToDecrypt);
@@ -4004,6 +4019,10 @@ bool wallet2::load_keys(const std::string& keys_file_name, const epee::wipeable_
m_segregation_height = field_segregation_height;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, ignore_fractional_outputs, int, Int, false, true);
m_ignore_fractional_outputs = field_ignore_fractional_outputs;
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, ignore_outputs_above, uint64_t, Uint64, false, MONEY_SUPPLY);
+ m_ignore_outputs_above = field_ignore_outputs_above;
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, ignore_outputs_below, uint64_t, Uint64, false, 0);
+ m_ignore_outputs_below = field_ignore_outputs_below;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, track_uses, int, Int, false, false);
m_track_uses = field_track_uses;
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, inactivity_lock_timeout, uint32_t, Uint, false, DEFAULT_INACTIVITY_LOCK_TIMEOUT);
@@ -5570,6 +5589,11 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
const std::string address_file = m_wallet_file + ".address.txt";
r = save_to_file(address_file, m_account.get_public_address_str(m_nettype), true);
THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_wallet_file);
+ // remove old address file
+ r = boost::filesystem::remove(old_address_file);
+ if (!r) {
+ LOG_ERROR("error removing file: " << old_address_file);
+ }
}
// remove old wallet file
r = boost::filesystem::remove(old_file);
@@ -5581,11 +5605,6 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
if (!r) {
LOG_ERROR("error removing file: " << old_keys_file);
}
- // remove old address file
- r = boost::filesystem::remove(old_address_file);
- if (!r) {
- LOG_ERROR("error removing file: " << old_address_file);
- }
// remove old message store file
if (boost::filesystem::exists(old_mms_file))
{
@@ -8599,6 +8618,11 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
const transfer_details& td = m_transfers[i];
if (!is_spent(td, false) && !td.m_frozen && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
{
+ if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below)
+ {
+ MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
+ continue;
+ }
LOG_PRINT_L2("We can use " << i << " alone: " << print_money(td.amount()));
picks.push_back(i);
return picks;
@@ -8614,10 +8638,20 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
const transfer_details& td = m_transfers[i];
if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.is_rct() && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
{
+ if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below)
+ {
+ MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
+ continue;
+ }
LOG_PRINT_L2("Considering input " << i << ", " << print_money(td.amount()));
for (size_t j = i + 1; j < m_transfers.size(); ++j)
{
const transfer_details& td2 = m_transfers[j];
+ if (td2.amount() > m_ignore_outputs_above || td2.amount() < m_ignore_outputs_below)
+ {
+ MDEBUG("Ignoring output " << j << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
+ continue;
+ }
if (!is_spent(td2, false) && !td2.m_frozen && !td.m_key_image_partial && td2.is_rct() && td.amount() + td2.amount() >= needed_money && is_transfer_unlocked(td2) && td2.m_subaddr_index == td.m_subaddr_index)
{
// update our picks if those outputs are less related than any we
@@ -9317,11 +9351,16 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
const transfer_details& td = m_transfers[i];
if (m_ignore_fractional_outputs && td.amount() < fractional_threshold)
{
- MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below threshold " << print_money(fractional_threshold));
+ MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below fractional threshold " << print_money(fractional_threshold));
continue;
}
if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
{
+ if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below)
+ {
+ MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]");
+ continue;
+ }
const uint32_t index_minor = td.m_subaddr_index.minor;
auto find_predicate = [&index_minor](const std::pair<uint32_t, std::vector<size_t>>& x) { return x.first == index_minor; };
if ((td.is_rct()) || is_valid_decomposed_amount(td.amount()))
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 1469b4c00..52118c426 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -1019,8 +1019,6 @@ private:
void set_default_priority(uint32_t p) { m_default_priority = p; }
bool auto_refresh() const { return m_auto_refresh; }
void auto_refresh(bool r) { m_auto_refresh = r; }
- bool confirm_missing_payment_id() const { return m_confirm_missing_payment_id; }
- void confirm_missing_payment_id(bool always) { m_confirm_missing_payment_id = always; }
AskPasswordType ask_password() const { return m_ask_password; }
void ask_password(AskPasswordType ask) { m_ask_password = ask; }
void set_min_output_count(uint32_t count) { m_min_output_count = count; }
@@ -1047,6 +1045,10 @@ private:
void ignore_fractional_outputs(bool value) { m_ignore_fractional_outputs = value; }
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; }
+ uint64_t ignore_outputs_above() const { return m_ignore_outputs_above; }
+ void ignore_outputs_above(uint64_t value) { m_ignore_outputs_above = value; }
+ uint64_t ignore_outputs_below() const { return m_ignore_outputs_below; }
+ void ignore_outputs_below(uint64_t value) { m_ignore_outputs_below = value; }
bool track_uses() const { return m_track_uses; }
void track_uses(bool value) { m_track_uses = value; }
BackgroundMiningSetupType setup_background_mining() const { return m_setup_background_mining; }
@@ -1351,7 +1353,7 @@ private:
* \param password Password of wallet file
*/
bool load_keys(const std::string& keys_file_name, const epee::wipeable_string& password);
- void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
+ void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector<uint64_t> &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
bool should_skip_block(const cryptonote::block &b, uint64_t height) const;
void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const parsed_block &parsed_block, const crypto::hash& bl_id, uint64_t height, const std::vector<tx_cache_data> &tx_cache_data, size_t tx_cache_data_offset, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
void detach_blockchain(uint64_t height, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
@@ -1496,7 +1498,6 @@ private:
// If m_refresh_from_block_height is explicitly set to zero we need this to differentiate it from the case that
// 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;
AskPasswordType m_ask_password;
uint32_t m_min_output_count;
@@ -1510,6 +1511,8 @@ private:
bool m_key_reuse_mitigation2;
uint64_t m_segregation_height;
bool m_ignore_fractional_outputs;
+ uint64_t m_ignore_outputs_above;
+ uint64_t m_ignore_outputs_below;
bool m_track_uses;
uint32_t m_inactivity_lock_timeout;
BackgroundMiningSetupType m_setup_background_mining;
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 0e0221c03..dbd42ab81 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -793,30 +793,9 @@ namespace tools
if (!payment_id.empty())
{
-
- /* Just to clarify */
- const std::string& payment_id_str = payment_id;
-
- crypto::hash long_payment_id;
- crypto::hash8 short_payment_id;
-
- /* Parse payment ID */
- if (wallet2::parse_long_payment_id(payment_id_str, long_payment_id)) {
- cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, long_payment_id);
- }
- else {
- er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
- er.message = "Payment id has invalid format: \"" + payment_id_str + "\", expected 64 character string";
- return false;
- }
-
- /* Append Payment ID data into extra */
- if (!cryptonote::add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
- er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
- er.message = "Something went wrong with payment_id. Please check its format: \"" + payment_id_str + "\", expected 64-character string";
- return false;
- }
-
+ er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
+ er.message = "Standalone payment IDs are obsolete. Use subaddresses or integrated addresses instead";
+ return false;
}
return true;
}
@@ -1003,6 +982,13 @@ namespace tools
std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices);
LOG_PRINT_L2("on_transfer_split called create_transactions_2");
+ if (ptx_vector.empty())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE;
+ er.message = "No transaction created";
+ return false;
+ }
+
return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay,
res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er);
}
@@ -1194,8 +1180,11 @@ namespace tools
crypto::hash payment_id;
if(cryptonote::get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
{
- desc.payment_id = epee::string_tools::pod_to_hex(payment_id8);
- has_encrypted_payment_id = true;
+ if (payment_id8 != crypto::null_hash8)
+ {
+ desc.payment_id = epee::string_tools::pod_to_hex(payment_id8);
+ has_encrypted_payment_id = true;
+ }
}
else if (cryptonote::get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
{
diff --git a/tests/functional_tests/cold_signing.py b/tests/functional_tests/cold_signing.py
index f915df77a..698217436 100755
--- a/tests/functional_tests/cold_signing.py
+++ b/tests/functional_tests/cold_signing.py
@@ -94,7 +94,6 @@ class ColdSigningTest():
print("Creating transaction in hot wallet")
dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000}
- payment_id = '1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde'
self.hot_wallet.refresh()
res = self.hot_wallet.export_outputs()
@@ -102,7 +101,7 @@ class ColdSigningTest():
res = self.cold_wallet.export_key_images(True)
self.hot_wallet.import_key_images(res.signed_key_images, offset = res.offset)
- res = self.hot_wallet.transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False)
+ res = self.hot_wallet.transfer([dst], ring_size = 11, get_tx_key = False)
assert len(res.tx_hash) == 32*2
txid = res.tx_hash
assert len(res.tx_key) == 0
@@ -124,7 +123,7 @@ class ColdSigningTest():
assert desc.amount_out == desc.amount_in - fee
assert desc.ring_size == 11
assert desc.unlock_time == 0
- assert desc.payment_id == payment_id
+ assert desc.payment_id in ['', '0000000000000000']
assert desc.change_amount == desc.amount_in - 1000000000000 - fee
assert desc.change_address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
assert desc.fee == fee
diff --git a/tests/functional_tests/multisig.py b/tests/functional_tests/multisig.py
index e0d8b06a4..e4e908aa1 100755
--- a/tests/functional_tests/multisig.py
+++ b/tests/functional_tests/multisig.py
@@ -272,7 +272,7 @@ class MultisigTest():
assert desc.amount_out == desc.amount_in - fee
assert desc.ring_size == 11
assert desc.unlock_time == 0
- assert desc.payment_id == '0000000000000000'
+ assert not 'payment_id' in desc or desc.payment_id in ['', '0000000000000000']
assert desc.change_amount == desc.amount_in - 1000000000000 - fee
assert desc.change_address == self.wallet_address
assert desc.fee == fee
diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py
index b4264f72d..0c942f48b 100755
--- a/tests/functional_tests/transfer.py
+++ b/tests/functional_tests/transfer.py
@@ -114,13 +114,19 @@ class TransferTest():
except: ok = True
assert ok
+ print ('Checking long payment IDs are rejected')
+ ok = False
+ try: self.wallet[0].transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False, get_tx_hex = True)
+ except: ok = True
+ assert ok
+
print ('Checking empty destination is rejected')
ok = False
try: self.wallet[0].transfer([], ring_size = 11, get_tx_key = False)
except: ok = True
assert ok
- res = self.wallet[0].transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False, get_tx_hex = True)
+ res = self.wallet[0].transfer([dst], ring_size = 11, get_tx_key = False, get_tx_hex = True)
assert len(res.tx_hash) == 32*2
txid = res.tx_hash
assert len(res.tx_key) == 0
@@ -156,7 +162,7 @@ class TransferTest():
assert e.type == 'block'
e = res.pending[0]
assert e.txid == txid
- assert e.payment_id == payment_id
+ assert e.payment_id in ['', '0000000000000000']
assert e.type == 'pending'
assert e.unlock_time == 0
assert e.subaddr_index.major == 0
@@ -189,7 +195,7 @@ class TransferTest():
assert e.type == 'block'
e = res.out[0]
assert e.txid == txid
- assert e.payment_id == payment_id
+ assert e.payment_id in ['', '0000000000000000']
assert e.type == 'out'
assert e.unlock_time == 0
assert e.subaddr_index.major == 0
@@ -205,7 +211,7 @@ class TransferTest():
assert res.transfers[0] == res.transfer
t = res.transfer
assert t.txid == txid
- assert t.payment_id == payment_id
+ assert t.payment_id in ['', '0000000000000000']
assert t.height == wallet_height - 1
assert t.timestamp > 0
assert t.amount == 0 # to self, so it's just "pay a fee" really
@@ -227,7 +233,7 @@ class TransferTest():
print("Creating transfer to another, manual relay")
dst = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1000000000000}
- res = self.wallet[0].transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = True, do_not_relay = True, get_tx_hex = True)
+ res = self.wallet[0].transfer([dst], ring_size = 11, get_tx_key = True, do_not_relay = True, get_tx_hex = True)
assert len(res.tx_hash) == 32*2
txid = res.tx_hash
assert len(res.tx_key) == 32*2
@@ -269,7 +275,7 @@ class TransferTest():
assert not 'failed' in res or len(res.failed) == 0
e = res.pool[0]
assert e.txid == txid
- assert e.payment_id == payment_id
+ assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored
assert e.type == 'pool'
assert e.unlock_time == 0
assert e.subaddr_index.major == 0
@@ -295,7 +301,7 @@ class TransferTest():
assert not 'failed' in res or len(res.failed) == 0
e = res['in'][0]
assert e.txid == txid
- assert e.payment_id == payment_id
+ assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored
assert e.type == 'in'
assert e.unlock_time == 0
assert e.subaddr_index.major == 0
@@ -318,7 +324,7 @@ class TransferTest():
dst0 = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000}
dst1 = {'address': '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW', 'amount': 1100000000000}
dst2 = {'address': '46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', 'amount': 1200000000000}
- res = self.wallet[0].transfer([dst0, dst1, dst2], ring_size = 11, payment_id = payment_id, get_tx_key = True)
+ res = self.wallet[0].transfer([dst0, dst1, dst2], ring_size = 11, get_tx_key = True)
assert len(res.tx_hash) == 32*2
txid = res.tx_hash
assert len(res.tx_key) == 32*2
@@ -357,7 +363,7 @@ class TransferTest():
assert len(e) == 1
e = e[0]
assert e.txid == txid
- assert e.payment_id == payment_id
+ assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored
assert e.type == 'out'
assert e.unlock_time == 0
assert e.subaddr_index.major == 0
@@ -385,7 +391,7 @@ class TransferTest():
assert len(e) == 1
e = e[0]
assert e.txid == txid
- assert e.payment_id == payment_id
+ assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored
assert e.type == 'in'
assert e.unlock_time == 0
assert e.subaddr_index.major == 0
@@ -412,7 +418,7 @@ class TransferTest():
assert len(e) == 1
e = e[0]
assert e.txid == txid
- assert e.payment_id == payment_id
+ assert e.payment_id in ["", "0000000000000000"] # long payment IDs are now ignored
assert e.type == 'in'
assert e.unlock_time == 0
assert e.subaddr_index.major == 0
@@ -521,7 +527,7 @@ class TransferTest():
res = self.wallet[1].get_bulk_payments()
assert len(res.payments) >= 3 # two txes to standard address were sent, plus one to integrated address
res = self.wallet[1].get_bulk_payments(payment_ids = ['1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde'])
- assert len(res.payments) >= 2 # two txes were sent with that payment id
+ assert not 'payments' in res or len(res.payments) == 0 # long payment IDs are now ignored on receipt
res = self.wallet[1].get_bulk_payments(payment_ids = ['ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'])
assert 'payments' not in res or len(res.payments) == 0 # none with that payment id
res = self.wallet[1].get_bulk_payments(payment_ids = ['1111111122222222' + '0'*48])
@@ -531,7 +537,7 @@ class TransferTest():
res = self.wallet[2].get_bulk_payments()
assert len(res.payments) >= 1 # one tx was sent
res = self.wallet[2].get_bulk_payments(payment_ids = ['1'*64, '1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde', '2'*64])
- assert len(res.payments) >= 1 # one tx was sent
+ assert not 'payments' in res or len(res.payments) == 0 # long payment IDs are now ignored
res = self.wallet[1].get_bulk_payments(["1111111122222222"])
assert len(res.payments) >= 1 # we have one of these
@@ -550,7 +556,7 @@ class TransferTest():
assert 'payments' not in res or len(res.payments) == 0
res = self.wallet[1].get_payments('1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde')
- assert len(res.payments) >= 2
+ assert 'payments' not in res or len(res.payments) == 0
res = self.wallet[1].get_payments('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')
assert 'payments' not in res or len(res.payments) == 0
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index cac1fa943..96825f54f 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -30,7 +30,6 @@ set(unit_tests_sources
account.cpp
apply_permutation.cpp
address_from_url.cpp
- ban.cpp
base58.cpp
blockchain_db.cpp
block_queue.cpp
@@ -68,6 +67,7 @@ set(unit_tests_sources
multiexp.cpp
multisig.cpp
net.cpp
+ node_server.cpp
notify.cpp
output_distribution.cpp
parse_amount.cpp
diff --git a/tests/unit_tests/mul_div.cpp b/tests/unit_tests/mul_div.cpp
index b11f715cd..e3f7c34f3 100644
--- a/tests/unit_tests/mul_div.cpp
+++ b/tests/unit_tests/mul_div.cpp
@@ -130,6 +130,19 @@ namespace
// Division by zero is UB, so can be tested correctly
}
+ TEST(div128_64, handles_zero)
+ {
+ uint64_t qhi, qlo, rhi, rlo;
+
+ div128_64(0, 0, 7, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0);
+ ASSERT_EQ(qhi, 0);
+ ASSERT_EQ(qlo, 0);
+
+ // Division by zero is UB, so can be tested correctly
+ }
+
TEST(div128_32, handles_one)
{
uint32_t reminder;
@@ -147,6 +160,23 @@ namespace
ASSERT_EQ(lo, 0);
}
+ TEST(div128_64, handles_one)
+ {
+ uint64_t qhi, qlo, rhi, rlo;
+
+ div128_64(0, 7, 1, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0);
+ ASSERT_EQ(qhi, 0);
+ ASSERT_EQ(qlo, 7);
+
+ div128_64(7, 0, 1, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0);
+ ASSERT_EQ(qhi, 7);
+ ASSERT_EQ(qlo, 0);
+ }
+
TEST(div128_32, handles_if_dividend_less_divider)
{
uint32_t reminder;
@@ -159,6 +189,17 @@ namespace
ASSERT_EQ(lo, 0);
}
+ TEST(div128_64, handles_if_dividend_less_divider)
+ {
+ uint64_t qhi, qlo, rhi, rlo;
+
+ div128_64(0, 1383746, 1645825, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 1383746);
+ ASSERT_EQ(qhi, 0);
+ ASSERT_EQ(qlo, 0);
+ }
+
TEST(div128_32, handles_if_dividend_dwords_less_divider)
{
uint32_t reminder;
@@ -171,6 +212,17 @@ namespace
ASSERT_EQ(lo, 0x9084FC024383E48C);
}
+ TEST(div128_64, handles_if_dividend_dwords_less_divider)
+ {
+ uint64_t qhi, qlo, rhi, rlo;
+
+ div128_64(0x5AD629E441074F28, 0x0DBCAB2B231081F1, 0xFE735CD6, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0xB9C924E9);
+ ASSERT_EQ(qhi, 0x000000005B63C274);
+ ASSERT_EQ(qlo, 0x9084FC024383E48C);
+ }
+
TEST(div128_32, works_correctly)
{
uint32_t reminder;
@@ -202,4 +254,68 @@ namespace
ASSERT_EQ(hi, 0x00000000f812c1f8);
ASSERT_EQ(lo, 0xddf2fdb09bc2e2e9);
}
+
+ TEST(div128_64, works_correctly)
+ {
+ uint64_t qhi, qlo, rhi, rlo;
+
+ div128_64(2, 0, 2, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0);
+ ASSERT_EQ(qhi, 1);
+ ASSERT_EQ(qlo, 0);
+
+ div128_64(0xffffffffffffffff, 0, 0xffffffff, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0);
+ ASSERT_EQ(qhi, 0x0000000100000001);
+ ASSERT_EQ(qlo, 0);
+
+ div128_64(0xffffffffffffffff, 5846, 0xffffffff, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 5846);
+ ASSERT_EQ(qhi, 0x0000000100000001);
+ ASSERT_EQ(qlo, 0);
+
+ div128_64(0xffffffffffffffff - 1, 0, 0xffffffff, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0xfffffffe);
+ ASSERT_EQ(qhi, 0x0000000100000000);
+ ASSERT_EQ(qlo, 0xfffffffefffffffe);
+
+ div128_64(0x2649372534875028, 0xaedbfedc5adbc739, 0x27826534, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0x1a6dc2e5);
+ ASSERT_EQ(qhi, 0x00000000f812c1f8);
+ ASSERT_EQ(qlo, 0xddf2fdb09bc2e2e9);
+ }
+
+ TEST(div128_64, divisor_above_32_bit)
+ {
+ uint64_t qhi, qlo, rhi, rlo;
+
+ div128_64(0, 0xffffffff, (uint64_t)0x100000000, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0xffffffff);
+ ASSERT_EQ(qhi, 0);
+ ASSERT_EQ(qlo, 0);
+
+ div128_64(0, 65, 4, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 1);
+ ASSERT_EQ(qhi, 0);
+ ASSERT_EQ(qlo, 16);
+
+ div128_64(405997335029502627ull, 2552775575832427192ull, 489327483788363ull, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 198332080500810ull);
+ ASSERT_EQ(qhi, 829ull);
+ ASSERT_EQ(qlo, 13000245803763621514ull);
+
+ div128_64(405997335029502627ull, 2552775575832427192ull, 1ull, &qhi, &qlo, &rhi, &rlo);
+ ASSERT_EQ(rhi, 0);
+ ASSERT_EQ(rlo, 0);
+ ASSERT_EQ(qhi, 405997335029502627ull);
+ ASSERT_EQ(qlo, 2552775575832427192ull);
+ }
}
diff --git a/tests/unit_tests/net.cpp b/tests/unit_tests/net.cpp
index 253280d4d..262541bd2 100644
--- a/tests/unit_tests/net.cpp
+++ b/tests/unit_tests/net.cpp
@@ -893,7 +893,8 @@ TEST(dandelionpp_map, empty)
TEST(dandelionpp_map, zero_stems)
{
std::vector<boost::uuids::uuid> connections{6};
- std::generate(connections.begin(), connections.end(), boost::uuids::random_generator{});
+ for (auto &c: connections)
+ c = boost::uuids::random_generator{}();
net::dandelionpp::connection_map mapper{connections, 0};
EXPECT_EQ(mapper.begin(), mapper.end());
@@ -917,7 +918,8 @@ TEST(dandelionpp_map, zero_stems)
TEST(dandelionpp_map, dropped_connection)
{
std::vector<boost::uuids::uuid> connections{6};
- std::generate(connections.begin(), connections.end(), boost::uuids::random_generator{});
+ for (auto &c: connections)
+ c = boost::uuids::random_generator{}();
std::sort(connections.begin(), connections.end());
// select 3 of 6 outgoing connections
@@ -953,7 +955,8 @@ TEST(dandelionpp_map, dropped_connection)
}
std::map<boost::uuids::uuid, boost::uuids::uuid> mapping;
std::vector<boost::uuids::uuid> in_connections{9};
- std::generate(in_connections.begin(), in_connections.end(), boost::uuids::random_generator{});
+ for (auto &c: in_connections)
+ c = boost::uuids::random_generator{}();
{
std::map<boost::uuids::uuid, std::size_t> used;
std::multimap<boost::uuids::uuid, boost::uuids::uuid> inverse_mapping;
diff --git a/tests/unit_tests/ban.cpp b/tests/unit_tests/node_server.cpp
index 86d546387..2c89323c7 100644
--- a/tests/unit_tests/ban.cpp
+++ b/tests/unit_tests/node_server.cpp
@@ -260,5 +260,42 @@ TEST(ban, ignores_port)
ASSERT_FALSE(is_blocked(server,MAKE_IPV4_ADDRESS_PORT(1,2,3,4,6)));
}
+TEST(node_server, bind_same_p2p_port)
+{
+ const auto new_node = []() -> std::unique_ptr<Server> {
+ test_core pr_core;
+ cryptonote::t_cryptonote_protocol_handler<test_core> cprotocol(pr_core, NULL);
+ std::unique_ptr<Server> server(new Server(cprotocol));
+ cprotocol.set_p2p_endpoint(server.get());
+
+ return server;
+ };
+
+ const auto init = [](const std::unique_ptr<Server>& server, const char* port) -> bool {
+ boost::program_options::options_description desc_options("Command line options");
+ cryptonote::core::init_options(desc_options);
+ Server::init_options(desc_options);
+
+ const char *argv[2] = {nullptr, nullptr};
+ boost::program_options::variables_map vm;
+ boost::program_options::store(boost::program_options::parse_command_line(1, argv, desc_options), vm);
+
+ vm.find(nodetool::arg_p2p_bind_port.name)->second = boost::program_options::variable_value(std::string(port), false);
+
+ boost::program_options::notify(vm);
+
+ return server->init(vm);
+ };
+
+ constexpr char port[] = "48080";
+ constexpr char port_another[] = "58080";
+
+ const auto node = new_node();
+ EXPECT_TRUE(init(node, port));
+
+ EXPECT_FALSE(init(new_node(), port));
+ EXPECT_TRUE(init(new_node(), port_another));
+}
+
namespace nodetool { template class node_server<cryptonote::t_cryptonote_protocol_handler<test_core>>; }
namespace cryptonote { template class t_cryptonote_protocol_handler<test_core>; }