aboutsummaryrefslogtreecommitdiff
path: root/tests/unit_tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit_tests')
-rw-r--r--tests/unit_tests/CMakeLists.txt1
-rw-r--r--tests/unit_tests/bulletproofs.cpp2
-rw-r--r--tests/unit_tests/bulletproofs_plus.cpp169
-rw-r--r--tests/unit_tests/levin.cpp113
-rw-r--r--tests/unit_tests/long_term_block_weight.cpp15
-rw-r--r--tests/unit_tests/multisig.cpp234
-rw-r--r--tests/unit_tests/node_server.cpp263
-rw-r--r--tests/unit_tests/serialization.cpp6
8 files changed, 727 insertions, 76 deletions
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index 556e0ec40..5f6b1e749 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -36,6 +36,7 @@ set(unit_tests_sources
block_reward.cpp
bootstrap_node_selector.cpp
bulletproofs.cpp
+ bulletproofs_plus.cpp
canonical_amounts.cpp
chacha.cpp
checkpoints.cpp
diff --git a/tests/unit_tests/bulletproofs.cpp b/tests/unit_tests/bulletproofs.cpp
index ee617938c..43a359a59 100644
--- a/tests/unit_tests/bulletproofs.cpp
+++ b/tests/unit_tests/bulletproofs.cpp
@@ -131,7 +131,7 @@ TEST(bulletproofs, multi_splitting)
}
rct::ctkeyV outSk;
- rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 0 };
+ rct::RCTConfig rct_config { rct::RangeProofPaddedBulletproof, 4 };
rct::rctSig s = rct::genRctSimple(rct::zero(), sc, destinations, inamounts, outamounts, available, mixRing, amount_keys, NULL, NULL, index, outSk, rct_config, hw::get_device("default"));
ASSERT_TRUE(rct::verRctSimple(s));
for (size_t i = 0; i < n_outputs; ++i)
diff --git a/tests/unit_tests/bulletproofs_plus.cpp b/tests/unit_tests/bulletproofs_plus.cpp
new file mode 100644
index 000000000..a64320233
--- /dev/null
+++ b/tests/unit_tests/bulletproofs_plus.cpp
@@ -0,0 +1,169 @@
+// Copyright (c) 2017-2020, 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.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#include "gtest/gtest.h"
+
+#include "string_tools.h"
+#include "ringct/rctOps.h"
+#include "ringct/rctSigs.h"
+#include "ringct/bulletproofs_plus.h"
+#include "cryptonote_basic/blobdatatype.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
+#include "device/device.hpp"
+#include "misc_log_ex.h"
+
+TEST(bulletproofs_plus, valid_zero)
+{
+ rct::BulletproofPlus proof = bulletproof_plus_PROVE(0, rct::skGen());
+ ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof));
+}
+
+TEST(bulletproofs_plus, valid_max)
+{
+ rct::BulletproofPlus proof = bulletproof_plus_PROVE(0xffffffffffffffff, rct::skGen());
+ ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof));
+}
+
+TEST(bulletproofs_plus, valid_random)
+{
+ for (int n = 0; n < 8; ++n)
+ {
+ rct::BulletproofPlus proof = bulletproof_plus_PROVE(crypto::rand<uint64_t>(), rct::skGen());
+ ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof));
+ }
+}
+
+TEST(bulletproofs_plus, valid_multi_random)
+{
+ for (int n = 0; n < 8; ++n)
+ {
+ size_t outputs = 2 + n;
+ std::vector<uint64_t> amounts;
+ rct::keyV gamma;
+ for (size_t i = 0; i < outputs; ++i)
+ {
+ amounts.push_back(crypto::rand<uint64_t>());
+ gamma.push_back(rct::skGen());
+ }
+ rct::BulletproofPlus proof = bulletproof_plus_PROVE(amounts, gamma);
+ ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof));
+ }
+}
+
+TEST(bulletproofs_plus, valid_aggregated)
+{
+ static const size_t N_PROOFS = 8;
+ std::vector<rct::BulletproofPlus> proofs(N_PROOFS);
+ for (size_t n = 0; n < N_PROOFS; ++n)
+ {
+ size_t outputs = 2 + n;
+ std::vector<uint64_t> amounts;
+ rct::keyV gamma;
+ for (size_t i = 0; i < outputs; ++i)
+ {
+ amounts.push_back(crypto::rand<uint64_t>());
+ gamma.push_back(rct::skGen());
+ }
+ proofs[n] = bulletproof_plus_PROVE(amounts, gamma);
+ }
+ ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proofs));
+}
+
+TEST(bulletproofs_plus, invalid_8)
+{
+ rct::key invalid_amount = rct::zero();
+ invalid_amount[8] = 1;
+ rct::BulletproofPlus proof = bulletproof_plus_PROVE(invalid_amount, rct::skGen());
+ ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof));
+}
+
+TEST(bulletproofs_plus, invalid_31)
+{
+ rct::key invalid_amount = rct::zero();
+ invalid_amount[31] = 1;
+ rct::BulletproofPlus proof = bulletproof_plus_PROVE(invalid_amount, rct::skGen());
+ ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof));
+}
+
+static const char * const torsion_elements[] =
+{
+ "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa",
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc85",
+ "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
+ "26e8958fc2b227b045c3f489f2ef98f0d5dfac05d3c63339b13802886d53fc05",
+ "0000000000000000000000000000000000000000000000000000000000000080",
+ "c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a",
+};
+
+TEST(bulletproofs_plus, invalid_torsion)
+{
+ rct::BulletproofPlus proof = bulletproof_plus_PROVE(7329838943733, rct::skGen());
+ ASSERT_TRUE(rct::bulletproof_plus_VERIFY(proof));
+ for (const auto &xs: torsion_elements)
+ {
+ rct::key x;
+ ASSERT_TRUE(epee::string_tools::hex_to_pod(xs, x));
+ ASSERT_FALSE(rct::isInMainSubgroup(x));
+ for (auto &k: proof.V)
+ {
+ const rct::key org_k = k;
+ rct::addKeys(k, org_k, x);
+ ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof));
+ k = org_k;
+ }
+ for (auto &k: proof.L)
+ {
+ const rct::key org_k = k;
+ rct::addKeys(k, org_k, x);
+ ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof));
+ k = org_k;
+ }
+ for (auto &k: proof.R)
+ {
+ const rct::key org_k = k;
+ rct::addKeys(k, org_k, x);
+ ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof));
+ k = org_k;
+ }
+ const rct::key org_A = proof.A;
+ rct::addKeys(proof.A, org_A, x);
+ ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof));
+ proof.A = org_A;
+ const rct::key org_A1 = proof.A1;
+ rct::addKeys(proof.A1, org_A1, x);
+ ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof));
+ proof.A1 = org_A1;
+ const rct::key org_B = proof.B;
+ rct::addKeys(proof.B, org_B, x);
+ ASSERT_FALSE(rct::bulletproof_plus_VERIFY(proof));
+ proof.B = org_B;
+ }
+}
diff --git a/tests/unit_tests/levin.cpp b/tests/unit_tests/levin.cpp
index 30d6f8133..069bc19b2 100644
--- a/tests/unit_tests/levin.cpp
+++ b/tests/unit_tests/levin.cpp
@@ -265,11 +265,17 @@ namespace
virtual void callback(cryptonote::levin::detail::p2p_context& context) override final
{}
- virtual void on_connection_new(cryptonote::levin::detail::p2p_context&) override final
- {}
+ virtual void on_connection_new(cryptonote::levin::detail::p2p_context& context) override final
+ {
+ if (notifier)
+ notifier->on_handshake_complete(context.m_connection_id, context.m_is_income);
+ }
- virtual void on_connection_close(cryptonote::levin::detail::p2p_context&) override final
- {}
+ virtual void on_connection_close(cryptonote::levin::detail::p2p_context& context) override final
+ {
+ if (notifier)
+ notifier->on_connection_close(context.m_connection_id);
+ }
public:
test_receiver()
@@ -306,6 +312,8 @@ namespace
{
return get_raw_message(notified_);
}
+
+ std::shared_ptr<cryptonote::levin::notify> notifier{};
};
class levin_notify : public ::testing::Test
@@ -343,13 +351,16 @@ namespace
EXPECT_EQ(connection_ids_.size(), connections_->get_connections_count());
}
- cryptonote::levin::notify make_notifier(const std::size_t noise_size, bool is_public, bool pad_txs)
+ std::shared_ptr<cryptonote::levin::notify> make_notifier(const std::size_t noise_size, bool is_public, bool pad_txs)
{
epee::byte_slice noise = nullptr;
if (noise_size)
noise = epee::levin::make_noise_notify(noise_size);
epee::net_utils::zone zone = is_public ? epee::net_utils::zone::public_ : epee::net_utils::zone::i2p;
- return cryptonote::levin::notify{io_service_, connections_, std::move(noise), zone, pad_txs, events_};
+ receiver_.notifier.reset(
+ new cryptonote::levin::notify{io_service_, connections_, std::move(noise), zone, pad_txs, events_}
+ );
+ return receiver_.notifier;
}
boost::uuids::random_generator random_generator_;
@@ -590,7 +601,8 @@ TEST_F(levin_notify, defaulted)
TEST_F(levin_notify, fluff_without_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -636,7 +648,8 @@ TEST_F(levin_notify, fluff_without_padding)
TEST_F(levin_notify, stem_without_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -708,7 +721,8 @@ TEST_F(levin_notify, stem_without_padding)
TEST_F(levin_notify, stem_no_outs_without_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(true);
@@ -764,7 +778,8 @@ TEST_F(levin_notify, stem_no_outs_without_padding)
TEST_F(levin_notify, local_without_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -836,7 +851,8 @@ TEST_F(levin_notify, local_without_padding)
TEST_F(levin_notify, forward_without_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -908,7 +924,8 @@ TEST_F(levin_notify, forward_without_padding)
TEST_F(levin_notify, block_without_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -937,7 +954,8 @@ TEST_F(levin_notify, block_without_padding)
TEST_F(levin_notify, none_without_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -966,7 +984,8 @@ TEST_F(levin_notify, none_without_padding)
TEST_F(levin_notify, fluff_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1012,7 +1031,8 @@ TEST_F(levin_notify, fluff_with_padding)
TEST_F(levin_notify, stem_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1079,7 +1099,8 @@ TEST_F(levin_notify, stem_with_padding)
TEST_F(levin_notify, stem_no_outs_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(true);
@@ -1135,7 +1156,8 @@ TEST_F(levin_notify, stem_no_outs_with_padding)
TEST_F(levin_notify, local_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1202,7 +1224,8 @@ TEST_F(levin_notify, local_with_padding)
TEST_F(levin_notify, forward_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1269,7 +1292,8 @@ TEST_F(levin_notify, forward_with_padding)
TEST_F(levin_notify, block_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1298,7 +1322,8 @@ TEST_F(levin_notify, block_with_padding)
TEST_F(levin_notify, none_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, true, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1327,7 +1352,8 @@ TEST_F(levin_notify, none_with_padding)
TEST_F(levin_notify, private_fluff_without_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, false, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1378,7 +1404,8 @@ TEST_F(levin_notify, private_fluff_without_padding)
TEST_F(levin_notify, private_stem_without_padding)
{
// private mode always uses fluff but marked as stem
- cryptonote::levin::notify notifier = make_notifier(0, false, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1429,7 +1456,8 @@ TEST_F(levin_notify, private_stem_without_padding)
TEST_F(levin_notify, private_local_without_padding)
{
// private mode always uses fluff but marked as stem
- cryptonote::levin::notify notifier = make_notifier(0, false, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1480,7 +1508,8 @@ TEST_F(levin_notify, private_local_without_padding)
TEST_F(levin_notify, private_forward_without_padding)
{
// private mode always uses fluff but marked as stem
- cryptonote::levin::notify notifier = make_notifier(0, false, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1531,7 +1560,8 @@ TEST_F(levin_notify, private_forward_without_padding)
TEST_F(levin_notify, private_block_without_padding)
{
// private mode always uses fluff but marked as stem
- cryptonote::levin::notify notifier = make_notifier(0, false, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1561,7 +1591,8 @@ TEST_F(levin_notify, private_block_without_padding)
TEST_F(levin_notify, private_none_without_padding)
{
// private mode always uses fluff but marked as stem
- cryptonote::levin::notify notifier = make_notifier(0, false, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1590,7 +1621,8 @@ TEST_F(levin_notify, private_none_without_padding)
TEST_F(levin_notify, private_fluff_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, false, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1640,7 +1672,8 @@ TEST_F(levin_notify, private_fluff_with_padding)
TEST_F(levin_notify, private_stem_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, false, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1690,7 +1723,8 @@ TEST_F(levin_notify, private_stem_with_padding)
TEST_F(levin_notify, private_local_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, false, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1740,7 +1774,8 @@ TEST_F(levin_notify, private_local_with_padding)
TEST_F(levin_notify, private_forward_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, false, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1790,7 +1825,8 @@ TEST_F(levin_notify, private_forward_with_padding)
TEST_F(levin_notify, private_block_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, false, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1819,7 +1855,8 @@ TEST_F(levin_notify, private_block_with_padding)
TEST_F(levin_notify, private_none_with_padding)
{
- cryptonote::levin::notify notifier = make_notifier(0, false, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, false, true);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < 10; ++count)
add_connection(count % 2 == 0);
@@ -1850,7 +1887,8 @@ TEST_F(levin_notify, stem_mappings)
{
static constexpr const unsigned test_connections_count = (CRYPTONOTE_DANDELIONPP_STEMS + 1) * 2;
- cryptonote::levin::notify notifier = make_notifier(0, true, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < test_connections_count; ++count)
add_connection(count % 2 == 0);
@@ -1973,7 +2011,8 @@ TEST_F(levin_notify, fluff_multiple)
{
static constexpr const unsigned test_connections_count = (CRYPTONOTE_DANDELIONPP_STEMS + 1) * 2;
- cryptonote::levin::notify notifier = make_notifier(0, true, false);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(0, true, false);
+ auto &notifier = *notifier_ptr;
for (unsigned count = 0; count < test_connections_count; ++count)
add_connection(count % 2 == 0);
@@ -2091,7 +2130,8 @@ TEST_F(levin_notify, noise)
txs[0].resize(1900, 'h');
const boost::uuids::uuid incoming_id = random_generator_();
- cryptonote::levin::notify notifier = make_notifier(2048, false, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(2048, false, true);
+ auto &notifier = *notifier_ptr;
{
const auto status = notifier.get_status();
@@ -2182,7 +2222,8 @@ TEST_F(levin_notify, noise_stem)
txs[0].resize(1900, 'h');
const boost::uuids::uuid incoming_id = random_generator_();
- cryptonote::levin::notify notifier = make_notifier(2048, false, true);
+ std::shared_ptr<cryptonote::levin::notify> notifier_ptr = make_notifier(2048, false, true);
+ auto &notifier = *notifier_ptr;
{
const auto status = notifier.get_status();
diff --git a/tests/unit_tests/long_term_block_weight.cpp b/tests/unit_tests/long_term_block_weight.cpp
index f075034bd..c0b057c9a 100644
--- a/tests/unit_tests/long_term_block_weight.cpp
+++ b/tests/unit_tests/long_term_block_weight.cpp
@@ -106,10 +106,16 @@ static uint32_t lcg()
}
+struct BlockchainAndPool
+{
+ cryptonote::tx_memory_pool txpool;
+ cryptonote::Blockchain bc;
+ BlockchainAndPool(): txpool(bc), bc(txpool) {}
+};
+
#define PREFIX_WINDOW(hf_version,window) \
- std::unique_ptr<cryptonote::Blockchain> bc; \
- cryptonote::tx_memory_pool txpool(*bc); \
- bc.reset(new cryptonote::Blockchain(txpool)); \
+ BlockchainAndPool bap; \
+ cryptonote::Blockchain *bc = &bap.bc; \
struct get_test_options { \
const std::pair<uint8_t, uint64_t> hard_forks[3]; \
const cryptonote::test_options test_options = { \
@@ -118,8 +124,7 @@ static uint32_t lcg()
}; \
get_test_options(): hard_forks{std::make_pair(1, (uint64_t)0), std::make_pair((uint8_t)hf_version, (uint64_t)1), std::make_pair((uint8_t)0, (uint64_t)0)} {} \
} opts; \
- cryptonote::Blockchain *blockchain = bc.get(); \
- bool r = blockchain->init(new TestDB(), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL); \
+ bool r = bc->init(new TestDB(), cryptonote::FAKECHAIN, true, &opts.test_options, 0, NULL); \
ASSERT_TRUE(r)
#define PREFIX(hf_version) PREFIX_WINDOW(hf_version, TEST_LONG_TERM_BLOCK_WEIGHT_WINDOW)
diff --git a/tests/unit_tests/multisig.cpp b/tests/unit_tests/multisig.cpp
index 79775960d..362a658de 100644
--- a/tests/unit_tests/multisig.cpp
+++ b/tests/unit_tests/multisig.cpp
@@ -26,12 +26,16 @@
// 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 "crypto/crypto.h"
+#include "multisig/multisig_account.h"
+#include "multisig/multisig_kex_msg.h"
+#include "ringct/rctOps.h"
+#include "wallet/wallet2.h"
+
#include "gtest/gtest.h"
#include <cstdint>
-#include "wallet/wallet2.h"
-
static const struct
{
const char *address;
@@ -86,59 +90,145 @@ static void make_wallet(unsigned int idx, tools::wallet2 &wallet)
}
}
-static std::vector<std::string> exchange_round(std::vector<tools::wallet2>& wallets, const std::vector<std::string>& mis)
+static std::vector<std::string> exchange_round(std::vector<tools::wallet2>& wallets, const std::vector<std::string>& infos)
{
std::vector<std::string> new_infos;
- for (size_t i = 0; i < wallets.size(); ++i) {
- new_infos.push_back(wallets[i].exchange_multisig_keys("", mis));
+ new_infos.reserve(infos.size());
+
+ for (size_t i = 0; i < wallets.size(); ++i)
+ {
+ new_infos.push_back(wallets[i].exchange_multisig_keys("", infos));
}
return new_infos;
}
+static void check_results(const std::vector<std::string> &intermediate_infos,
+ std::vector<tools::wallet2>& wallets,
+ std::uint32_t M)
+{
+ // check results
+ std::unordered_set<crypto::secret_key> unique_privkeys;
+ rct::key composite_pubkey = rct::identity();
+
+ wallets[0].decrypt_keys("");
+ crypto::public_key spend_pubkey = wallets[0].get_account().get_keys().m_account_address.m_spend_public_key;
+ crypto::secret_key view_privkey = wallets[0].get_account().get_keys().m_view_secret_key;
+ crypto::public_key view_pubkey;
+ EXPECT_TRUE(crypto::secret_key_to_public_key(view_privkey, view_pubkey));
+ wallets[0].encrypt_keys("");
+
+ for (size_t i = 0; i < wallets.size(); ++i)
+ {
+ EXPECT_TRUE(intermediate_infos[i].empty());
+ bool ready;
+ uint32_t threshold, total;
+ EXPECT_TRUE(wallets[i].multisig(&ready, &threshold, &total));
+ EXPECT_TRUE(ready);
+ EXPECT_TRUE(threshold == M);
+ EXPECT_TRUE(total == wallets.size());
+
+ wallets[i].decrypt_keys("");
+
+ if (i != 0)
+ {
+ // "equals" is transitive relation so we need only to compare first wallet's address to each others' addresses.
+ // no need to compare 0's address with itself.
+ EXPECT_TRUE(wallets[0].get_account().get_public_address_str(cryptonote::TESTNET) ==
+ wallets[i].get_account().get_public_address_str(cryptonote::TESTNET));
+
+ EXPECT_EQ(spend_pubkey, wallets[i].get_account().get_keys().m_account_address.m_spend_public_key);
+ EXPECT_EQ(view_privkey, wallets[i].get_account().get_keys().m_view_secret_key);
+ EXPECT_EQ(view_pubkey, wallets[i].get_account().get_keys().m_account_address.m_view_public_key);
+ }
+
+ // sum together unique multisig keys
+ for (const auto &privkey : wallets[i].get_account().get_keys().m_multisig_keys)
+ {
+ EXPECT_NE(privkey, crypto::null_skey);
+
+ if (unique_privkeys.find(privkey) == unique_privkeys.end())
+ {
+ unique_privkeys.insert(privkey);
+ crypto::public_key pubkey;
+ crypto::secret_key_to_public_key(privkey, pubkey);
+ EXPECT_NE(privkey, crypto::null_skey);
+ EXPECT_NE(pubkey, crypto::null_pkey);
+ EXPECT_NE(pubkey, rct::rct2pk(rct::identity()));
+ rct::addKeys(composite_pubkey, composite_pubkey, rct::pk2rct(pubkey));
+ }
+ }
+ wallets[i].encrypt_keys("");
+ }
+
+ // final key via sums should equal the wallets' public spend key
+ wallets[0].decrypt_keys("");
+ EXPECT_EQ(wallets[0].get_account().get_keys().m_account_address.m_spend_public_key, rct::rct2pk(composite_pubkey));
+ wallets[0].encrypt_keys("");
+}
+
static void make_wallets(std::vector<tools::wallet2>& wallets, unsigned int M)
{
ASSERT_TRUE(wallets.size() > 1 && wallets.size() <= KEYS_COUNT);
ASSERT_TRUE(M <= wallets.size());
+ std::uint32_t rounds_required = multisig::multisig_kex_rounds_required(wallets.size(), M);
+ std::uint32_t rounds_complete{0};
- std::vector<std::string> mis(wallets.size());
+ // initialize wallets, get first round multisig kex msgs
+ std::vector<std::string> initial_infos(wallets.size());
- for (size_t i = 0; i < wallets.size(); ++i) {
+ for (size_t i = 0; i < wallets.size(); ++i)
+ {
make_wallet(i, wallets[i]);
wallets[i].decrypt_keys("");
- mis[i] = wallets[i].get_multisig_info();
+ initial_infos[i] = wallets[i].get_multisig_first_kex_msg();
wallets[i].encrypt_keys("");
}
- for (auto& wallet: wallets) {
+ // wallets should not be multisig yet
+ for (const auto &wallet: wallets)
+ {
ASSERT_FALSE(wallet.multisig());
}
- std::vector<std::string> mxis;
- for (size_t i = 0; i < wallets.size(); ++i) {
- // it's ok to put all of multisig keys in this function. it throws in case of error
- mxis.push_back(wallets[i].make_multisig("", mis, M));
- }
+ // make wallets multisig, get second round kex messages (if appropriate)
+ std::vector<std::string> intermediate_infos(wallets.size());
- while (!mxis[0].empty()) {
- mxis = exchange_round(wallets, mxis);
+ for (size_t i = 0; i < wallets.size(); ++i)
+ {
+ intermediate_infos[i] = wallets[i].make_multisig("", initial_infos, M);
}
- for (size_t i = 0; i < wallets.size(); ++i) {
- ASSERT_TRUE(mxis[i].empty());
- bool ready;
- uint32_t threshold, total;
- ASSERT_TRUE(wallets[i].multisig(&ready, &threshold, &total));
- ASSERT_TRUE(ready);
- ASSERT_TRUE(threshold == M);
- ASSERT_TRUE(total == wallets.size());
-
- if (i != 0) {
- // "equals" is transitive relation so we need only to compare first wallet's address to each others' addresses. no need to compare 0's address with itself.
- ASSERT_TRUE(wallets[0].get_account().get_public_address_str(cryptonote::TESTNET) == wallets[i].get_account().get_public_address_str(cryptonote::TESTNET));
- }
+ ++rounds_complete;
+
+ // perform kex rounds until kex is complete
+ while (!intermediate_infos[0].empty())
+ {
+ bool ready{false};
+ wallets[0].multisig(&ready);
+ EXPECT_FALSE(ready);
+
+ intermediate_infos = exchange_round(wallets, intermediate_infos);
+
+ ++rounds_complete;
}
+
+ EXPECT_EQ(rounds_required, rounds_complete);
+
+ check_results(intermediate_infos, wallets, M);
+}
+
+TEST(multisig, make_1_2)
+{
+ std::vector<tools::wallet2> wallets(2);
+ make_wallets(wallets, 1);
+}
+
+TEST(multisig, make_1_3)
+{
+ std::vector<tools::wallet2> wallets(3);
+ make_wallets(wallets, 1);
}
TEST(multisig, make_2_2)
@@ -165,8 +255,88 @@ TEST(multisig, make_2_4)
make_wallets(wallets, 2);
}
-TEST(multisig, make_2_5)
+TEST(multisig, multisig_kex_msg)
{
- std::vector<tools::wallet2> wallets(5);
- make_wallets(wallets, 2);
+ using namespace multisig;
+
+ crypto::public_key pubkey1;
+ crypto::public_key pubkey2;
+ crypto::public_key pubkey3;
+ crypto::secret_key_to_public_key(rct::rct2sk(rct::skGen()), pubkey1);
+ crypto::secret_key_to_public_key(rct::rct2sk(rct::skGen()), pubkey2);
+ crypto::secret_key_to_public_key(rct::rct2sk(rct::skGen()), pubkey3);
+
+ crypto::secret_key signing_skey = rct::rct2sk(rct::skGen());
+ crypto::public_key signing_pubkey;
+ while(!crypto::secret_key_to_public_key(signing_skey, signing_pubkey))
+ {
+ signing_skey = rct::rct2sk(rct::skGen());
+ }
+
+ crypto::secret_key ancillary_skey = rct::rct2sk(rct::skGen());
+ while (ancillary_skey == crypto::null_skey)
+ ancillary_skey = rct::rct2sk(rct::skGen());
+
+ // misc. edge cases
+ EXPECT_NO_THROW((multisig_kex_msg{}));
+ EXPECT_ANY_THROW((multisig_kex_msg{multisig_kex_msg{}.get_msg()}));
+ EXPECT_ANY_THROW((multisig_kex_msg{"abc"}));
+ EXPECT_ANY_THROW((multisig_kex_msg{0, crypto::null_skey, std::vector<crypto::public_key>{}, crypto::null_skey}));
+ EXPECT_ANY_THROW((multisig_kex_msg{1, crypto::null_skey, std::vector<crypto::public_key>{}, crypto::null_skey}));
+ EXPECT_ANY_THROW((multisig_kex_msg{1, signing_skey, std::vector<crypto::public_key>{}, crypto::null_skey}));
+ EXPECT_ANY_THROW((multisig_kex_msg{1, crypto::null_skey, std::vector<crypto::public_key>{}, ancillary_skey}));
+
+ // test that messages are both constructible and reversible
+
+ // round 1
+ EXPECT_NO_THROW((multisig_kex_msg{
+ multisig_kex_msg{1, signing_skey, std::vector<crypto::public_key>{}, ancillary_skey}.get_msg()
+ }));
+ EXPECT_NO_THROW((multisig_kex_msg{
+ multisig_kex_msg{1, signing_skey, std::vector<crypto::public_key>{pubkey1}, ancillary_skey}.get_msg()
+ }));
+
+ // round 2
+ EXPECT_NO_THROW((multisig_kex_msg{
+ multisig_kex_msg{2, signing_skey, std::vector<crypto::public_key>{pubkey1}, ancillary_skey}.get_msg()
+ }));
+ EXPECT_NO_THROW((multisig_kex_msg{
+ multisig_kex_msg{2, signing_skey, std::vector<crypto::public_key>{pubkey1}, crypto::null_skey}.get_msg()
+ }));
+ EXPECT_NO_THROW((multisig_kex_msg{
+ multisig_kex_msg{2, signing_skey, std::vector<crypto::public_key>{pubkey1, pubkey2}, ancillary_skey}.get_msg()
+ }));
+ EXPECT_NO_THROW((multisig_kex_msg{
+ multisig_kex_msg{2, signing_skey, std::vector<crypto::public_key>{pubkey1, pubkey2, pubkey3}, crypto::null_skey}.get_msg()
+ }));
+
+ // test that keys can be recovered if stored in a message and the message's reverse
+
+ // round 1
+ multisig_kex_msg msg_rnd1{1, signing_skey, std::vector<crypto::public_key>{pubkey1}, ancillary_skey};
+ multisig_kex_msg msg_rnd1_reverse{msg_rnd1.get_msg()};
+ EXPECT_EQ(msg_rnd1.get_round(), 1);
+ EXPECT_EQ(msg_rnd1.get_round(), msg_rnd1_reverse.get_round());
+ EXPECT_EQ(msg_rnd1.get_signing_pubkey(), signing_pubkey);
+ EXPECT_EQ(msg_rnd1.get_signing_pubkey(), msg_rnd1_reverse.get_signing_pubkey());
+ EXPECT_EQ(msg_rnd1.get_msg_pubkeys().size(), 0);
+ EXPECT_EQ(msg_rnd1.get_msg_pubkeys().size(), msg_rnd1_reverse.get_msg_pubkeys().size());
+ EXPECT_EQ(msg_rnd1.get_msg_privkey(), ancillary_skey);
+ EXPECT_EQ(msg_rnd1.get_msg_privkey(), msg_rnd1_reverse.get_msg_privkey());
+
+ // round 2
+ multisig_kex_msg msg_rnd2{2, signing_skey, std::vector<crypto::public_key>{pubkey1, pubkey2}, ancillary_skey};
+ multisig_kex_msg msg_rnd2_reverse{msg_rnd2.get_msg()};
+ EXPECT_EQ(msg_rnd2.get_round(), 2);
+ EXPECT_EQ(msg_rnd2.get_round(), msg_rnd2_reverse.get_round());
+ EXPECT_EQ(msg_rnd2.get_signing_pubkey(), signing_pubkey);
+ EXPECT_EQ(msg_rnd2.get_signing_pubkey(), msg_rnd2_reverse.get_signing_pubkey());
+ ASSERT_EQ(msg_rnd2.get_msg_pubkeys().size(), 2);
+ ASSERT_EQ(msg_rnd2.get_msg_pubkeys().size(), msg_rnd2_reverse.get_msg_pubkeys().size());
+ EXPECT_EQ(msg_rnd2.get_msg_pubkeys()[0], pubkey1);
+ EXPECT_EQ(msg_rnd2.get_msg_pubkeys()[1], pubkey2);
+ EXPECT_EQ(msg_rnd2.get_msg_pubkeys()[0], msg_rnd2_reverse.get_msg_pubkeys()[0]);
+ EXPECT_EQ(msg_rnd2.get_msg_pubkeys()[1], msg_rnd2_reverse.get_msg_pubkeys()[1]);
+ EXPECT_EQ(msg_rnd2.get_msg_privkey(), crypto::null_skey);
+ EXPECT_EQ(msg_rnd2.get_msg_privkey(), msg_rnd2_reverse.get_msg_privkey());
}
diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp
index cab600b3d..7907e9a9a 100644
--- a/tests/unit_tests/node_server.cpp
+++ b/tests/unit_tests/node_server.cpp
@@ -35,6 +35,7 @@
#include "cryptonote_core/i_core_events.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.inl"
+#include <condition_variable>
#define MAKE_IPV4_ADDRESS(a,b,c,d) epee::net_utils::ipv4_network_address{MAKE_IP(a,b,c,d),0}
#define MAKE_IPV4_ADDRESS_PORT(a,b,c,d,e) epee::net_utils::ipv4_network_address{MAKE_IP(a,b,c,d),e}
@@ -303,6 +304,9 @@ TEST(node_server, bind_same_p2p_port)
Relevant part about REUSEADDR from man:
https://www.man7.org/linux/man-pages/man7/ip.7.html
+
+ For Mac OSX, set the following alias, before running the test, or else it will fail:
+ sudo ifconfig lo0 alias 127.0.0.2
*/
vm.find(nodetool::arg_p2p_bind_ip.name)->second = boost::program_options::variable_value(std::string("127.0.0.2"), false);
vm.find(nodetool::arg_p2p_bind_port.name)->second = boost::program_options::variable_value(std::string(port), false);
@@ -906,5 +910,264 @@ TEST(cryptonote_protocol_handler, race_condition)
remove_tree(dir);
}
+TEST(node_server, race_condition)
+{
+ struct contexts {
+ using cryptonote = cryptonote::cryptonote_connection_context;
+ using p2p = nodetool::p2p_connection_context_t<cryptonote>;
+ };
+ using context_t = contexts::cryptonote;
+ using options_t = boost::program_options::variables_map;
+ using options_description_t = boost::program_options::options_description;
+ using worker_t = std::thread;
+ struct protocol_t {
+ private:
+ using p2p_endpoint_t = nodetool::i_p2p_endpoint<context_t>;
+ using lock_t = std::mutex;
+ using condition_t = std::condition_variable_any;
+ using unique_lock_t = std::unique_lock<lock_t>;
+ p2p_endpoint_t *p2p_endpoint;
+ lock_t lock;
+ condition_t condition;
+ bool started{};
+ size_t counter{};
+ public:
+ using payload_t = cryptonote::CORE_SYNC_DATA;
+ using blob_t = cryptonote::blobdata;
+ using connection_context = context_t;
+ using payload_type = payload_t;
+ using relay_t = cryptonote::relay_method;
+ using string_t = std::string;
+ using span_t = epee::span<const uint8_t>;
+ using blobs_t = epee::span<const cryptonote::blobdata>;
+ using connections_t = std::list<cryptonote::connection_info>;
+ using block_queue_t = cryptonote::block_queue;
+ using stripes_t = std::pair<uint32_t, uint32_t>;
+ using byte_stream_t = epee::byte_stream;
+ struct core_events_t: cryptonote::i_core_events {
+ uint64_t get_current_blockchain_height() const override { return {}; }
+ bool is_synchronized() const override { return {}; }
+ void on_transactions_relayed(blobs_t blobs, relay_t relay) override {}
+ };
+ int handle_invoke_map(bool is_notify, int command, const span_t in, byte_stream_t &out, context_t &context, bool &handled) {
+ return {};
+ }
+ bool on_idle() {
+ if (not p2p_endpoint)
+ return {};
+ {
+ unique_lock_t guard(lock);
+ if (not started)
+ started = true;
+ else
+ return {};
+ }
+ std::vector<blob_t> txs(128 / 64 * 1024 * 1024, blob_t(1, 'x'));
+ worker_t worker([this]{
+ p2p_endpoint->for_each_connection(
+ [this](context_t &, uint64_t, uint32_t){
+ {
+ unique_lock_t guard(lock);
+ ++counter;
+ condition.notify_all();
+ condition.wait(guard, [this]{ return counter >= 3; });
+ }
+ std::this_thread::sleep_for(std::chrono::milliseconds(8));
+ return false;
+ }
+ );
+ });
+ {
+ unique_lock_t guard(lock);
+ ++counter;
+ condition.notify_all();
+ condition.wait(guard, [this]{ return counter >= 3; });
+ ++counter;
+ condition.notify_all();
+ condition.wait(guard, [this]{ return counter >= 5; });
+ }
+ p2p_endpoint->send_txs(
+ std::move(txs),
+ epee::net_utils::zone::public_,
+ {},
+ relay_t::fluff
+ );
+ worker.join();
+ return {};
+ }
+ bool init(const options_t &options) { return {}; }
+ bool deinit() { return {}; }
+ void set_p2p_endpoint(p2p_endpoint_t *p2p_endpoint) {
+ this->p2p_endpoint = p2p_endpoint;
+ }
+ bool process_payload_sync_data(const payload_t &payload, contexts::p2p &context, bool is_inital) {
+ context.m_state = context_t::state_normal;
+ context.m_needed_objects.resize(512 * 1024);
+ {
+ unique_lock_t guard(lock);
+ ++counter;
+ condition.notify_all();
+ condition.wait(guard, [this]{ return counter >= 3; });
+ ++counter;
+ condition.notify_all();
+ condition.wait(guard, [this]{ return counter >= 5; });
+ }
+ return true;
+ }
+ bool get_payload_sync_data(blob_t &blob) { return {}; }
+ bool get_payload_sync_data(payload_t &payload) { return {}; }
+ bool on_callback(context_t &context) { return {}; }
+ core_events_t &get_core(){ static core_events_t core_events; return core_events;}
+ void log_connections() {}
+ connections_t get_connections() { return {}; }
+ const block_queue_t &get_block_queue() const {
+ static block_queue_t block_queue;
+ return block_queue;
+ }
+ void stop() {}
+ void on_connection_close(context_t &context) {}
+ void set_max_out_peers(unsigned int max) {}
+ bool no_sync() const { return {}; }
+ void set_no_sync(bool value) {}
+ string_t get_peers_overview() const { return {}; }
+ stripes_t get_next_needed_pruning_stripe() const { return {}; }
+ bool needs_new_sync_connections() const { return {}; }
+ bool is_busy_syncing() { return {}; }
+ };
+ using node_server_t = nodetool::node_server<protocol_t>;
+ auto conduct_test = [](protocol_t &protocol){
+ struct messages {
+ struct core {
+ using sync = cryptonote::CORE_SYNC_DATA;
+ };
+ using handshake = nodetool::COMMAND_HANDSHAKE_T<core::sync>;
+ };
+ using handler_t = epee::levin::async_protocol_handler<context_t>;
+ using connection_t = epee::net_utils::connection<handler_t>;
+ using connection_ptr = boost::shared_ptr<connection_t>;
+ using shared_state_t = typename connection_t::shared_state;
+ using shared_state_ptr = std::shared_ptr<shared_state_t>;
+ using io_context_t = boost::asio::io_service;
+ using work_t = boost::asio::io_service::work;
+ using work_ptr = std::shared_ptr<work_t>;
+ using workers_t = std::vector<std::thread>;
+ using endpoint_t = boost::asio::ip::tcp::endpoint;
+ using event_t = epee::simple_event;
+ struct command_handler_t: epee::levin::levin_commands_handler<context_t> {
+ using span_t = epee::span<const uint8_t>;
+ using byte_stream_t = epee::byte_stream;
+ int invoke(int, const span_t, byte_stream_t &, context_t &) override { return {}; }
+ int notify(int, const span_t, context_t &) override { return {}; }
+ void callback(context_t &) override {}
+ void on_connection_new(context_t &) override {}
+ void on_connection_close(context_t &) override {}
+ ~command_handler_t() override {}
+ static void destroy(epee::levin::levin_commands_handler<context_t>* ptr) { delete ptr; }
+ };
+ io_context_t io_context;
+ work_ptr work = std::make_shared<work_t>(io_context);
+ workers_t workers;
+ while (workers.size() < 4) {
+ workers.emplace_back([&io_context]{
+ io_context.run();
+ });
+ }
+ io_context.post([&]{
+ protocol.on_idle();
+ });
+ io_context.post([&]{
+ protocol.on_idle();
+ });
+ shared_state_ptr shared_state = std::make_shared<shared_state_t>();
+ shared_state->set_handler(new command_handler_t, &command_handler_t::destroy);
+ connection_ptr conn{new connection_t(io_context, shared_state, {}, {})};
+ endpoint_t endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 48080);
+ conn->socket().connect(endpoint);
+ conn->socket().set_option(boost::asio::ip::tcp::socket::reuse_address(true));
+ conn->start({}, {});
+ context_t context;
+ conn->get_context(context);
+ event_t handshaked;
+ typename messages::handshake::request_t msg{{
+ ::config::NETWORK_ID,
+ 58080,
+ }};
+ epee::net_utils::async_invoke_remote_command2<typename messages::handshake::response>(
+ context,
+ messages::handshake::ID,
+ msg,
+ *shared_state,
+ [conn, &handshaked](int code, const typename messages::handshake::response &msg, context_t &context){
+ EXPECT_TRUE(code >= 0);
+ handshaked.raise();
+ },
+ P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT
+ );
+ handshaked.wait();
+ conn->strand_.post([conn]{
+ conn->cancel();
+ });
+ conn.reset();
+ work.reset();
+ for (auto& w: workers) {
+ w.join();
+ }
+ };
+ using path_t = boost::filesystem::path;
+ using ec_t = boost::system::error_code;
+ auto create_dir = []{
+ ec_t ec;
+ path_t path = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path("daemon-%%%%%%%%%%%%%%%%", ec);
+ if (ec)
+ return path_t{};
+ auto success = boost::filesystem::create_directory(path, ec);
+ if (not ec && success)
+ return path;
+ return path_t{};
+ };
+ auto remove_tree = [](const path_t &path){
+ ec_t ec;
+ boost::filesystem::remove_all(path, ec);
+ };
+ const auto dir = create_dir();
+ ASSERT_TRUE(not dir.empty());
+ protocol_t protocol{};
+ node_server_t node_server(protocol);
+ protocol.set_p2p_endpoint(&node_server);
+ node_server.init(
+ [&dir]{
+ options_t options;
+ boost::program_options::store(
+ boost::program_options::command_line_parser({
+ "--p2p-bind-ip=127.0.0.1",
+ "--p2p-bind-port=48080",
+ "--out-peers=0",
+ "--data-dir",
+ dir.string(),
+ "--no-igd",
+ "--add-exclusive-node=127.0.0.1:48080",
+ "--check-updates=disabled",
+ "--disable-dns-checkpoints",
+ }).options([]{
+ options_description_t options_description{};
+ cryptonote::core::init_options(options_description);
+ node_server_t::init_options(options_description);
+ return options_description;
+ }()).run(),
+ options
+ );
+ return options;
+ }()
+ );
+ worker_t worker([&]{
+ node_server.run();
+ });
+ conduct_test(protocol);
+ node_server.send_stop_signal();
+ worker.join();
+ node_server.deinit();
+ remove_tree(dir);
+}
+
namespace nodetool { template class node_server<cryptonote::t_cryptonote_protocol_handler<test_core>>; }
namespace cryptonote { template class t_cryptonote_protocol_handler<test_core>; }
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index 535752665..f4c73d3d5 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -132,7 +132,8 @@ TEST(Serialization, BinaryArchiveInts) {
ASSERT_EQ(8, oss.str().size());
ASSERT_EQ(string("\0\0\0\0\xff\0\0\0", 8), oss.str());
- binary_archive<false> iar{epee::strspan<std::uint8_t>(oss.str())};
+ const std::string s = oss.str();
+ binary_archive<false> iar{epee::strspan<std::uint8_t>(s)};
iar.serialize_int(x1);
ASSERT_EQ(8, iar.getpos());
ASSERT_TRUE(iar.good());
@@ -150,7 +151,8 @@ TEST(Serialization, BinaryArchiveVarInts) {
ASSERT_EQ(6, oss.str().size());
ASSERT_EQ(string("\x80\x80\x80\x80\xF0\x1F", 6), oss.str());
- binary_archive<false> iar{epee::strspan<std::uint8_t>(oss.str())};
+ const std::string s = oss.str();
+ binary_archive<false> iar{epee::strspan<std::uint8_t>(s)};
iar.serialize_varint(x1);
ASSERT_TRUE(iar.good());
ASSERT_EQ(x, x1);