Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions test/chasers/chaser_check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,21 @@ struct chaser_check_setup_fixture
map->merge(*get_hashes().map);
return map;
}

/// Take work from the check chaser until count hashes (bounded).
map_ptr take(size_t count)
{
using namespace std::chrono;
const auto map = chaser_check::empty_map();
const auto deadline = steady_clock::now() + seconds(10);
while (steady_clock::now() < deadline && map->size() < count)
{
map->merge(*get_hashes().map);
std::this_thread::sleep_for(milliseconds(10));
}

return map;
}
};

// Mainnet blocks 1 and 2 are unassociated candidates.
Expand Down Expand Up @@ -393,9 +408,9 @@ BOOST_FIXTURE_TEST_CASE(chaser_check__get_hashes__candidates__expected_map, chas
const auto work = get_hashes();
BOOST_REQUIRE(!work.ec);
BOOST_REQUIRE(work.racer);
BOOST_REQUIRE_EQUAL(work.map->size(), one);
BOOST_REQUIRE_EQUAL(work.map->size(), two);
BOOST_REQUIRE(work.map->exists(p2p_compact_setup_fixture::block1().hash()));
BOOST_REQUIRE(get_hashes().map->exists(p2p_compact_setup_fixture::block2().hash()));
BOOST_REQUIRE(work.map->exists(p2p_compact_setup_fixture::block2().hash()));
BOOST_REQUIRE(get_hashes().map->empty());
}

Expand Down Expand Up @@ -441,7 +456,6 @@ BOOST_FIXTURE_TEST_CASE(chaser_check__checked__window_downloaded__windowed, chas
BOOST_REQUIRE(handshake(peer_services));
receive(get_data::command);
send(peer::block::command, p2p_compact_setup_fixture::block1().to_data(true));
receive(get_data::command);
send(peer::block::command, p2p_compact_setup_fixture::block2().to_data(true));

chases::windowed windowed{};
Expand All @@ -460,8 +474,11 @@ BOOST_FIXTURE_TEST_CASE(chaser_check__valid__requested_not_positioned__no_downlo

chases::stall stall{};
BOOST_REQUIRE(await(stall));
BOOST_REQUIRE(get_hashes().map->exists(p2p_compact_setup_fixture::block1().hash()));
BOOST_REQUIRE(get_hashes().map->exists(p2p_compact_setup_fixture::block2().hash()));

const auto map = get_hashes().map;
BOOST_REQUIRE_EQUAL(map->size(), two);
BOOST_REQUIRE(map->exists(p2p_compact_setup_fixture::block1().hash()));
BOOST_REQUIRE(map->exists(p2p_compact_setup_fixture::block2().hash()));
BOOST_REQUIRE(get_hashes().map->empty());
}

Expand Down Expand Up @@ -510,8 +527,9 @@ BOOST_FIXTURE_TEST_CASE(protocol_block_in_31800__subscribed__candidates__get_dat

const auto request = get_data::deserialize(node_version->value, receive(get_data::command));
BOOST_REQUIRE(request);
BOOST_REQUIRE_EQUAL(request->items.size(), one);
BOOST_REQUIRE_EQUAL(request->items.size(), two);
BOOST_REQUIRE(request->items.front().hash == p2p_compact_setup_fixture::block1().hash());
BOOST_REQUIRE(request->items.back().hash == p2p_compact_setup_fixture::block2().hash());
}

BOOST_FIXTURE_TEST_CASE(protocol_block_in_31800__handle_receive_block__unrequested__not_stopped, chaser_check_candidate_setup_fixture)
Expand Down Expand Up @@ -611,9 +629,10 @@ BOOST_FIXTURE_TEST_CASE(protocol_block_in_31800__handle_chase__stall_with_work__
node_.notify({}, chases::stall{ 42 });
BOOST_REQUIRE_THROW(receive(pong::command), boost::system::system_error);

const auto map = get_hashes().map;
BOOST_REQUIRE_EQUAL(map->size(), one);
const auto map = take(two);
BOOST_REQUIRE_EQUAL(map->size(), two);
BOOST_REQUIRE(map->exists(p2p_compact_setup_fixture::block1().hash()));
BOOST_REQUIRE(map->exists(p2p_compact_setup_fixture::block2().hash()));
}

BOOST_FIXTURE_TEST_CASE(protocol_block_in_31800__handle_chase__download_then_split__stopped, chaser_check_candidate_setup_fixture)
Expand Down Expand Up @@ -672,6 +691,9 @@ BOOST_FIXTURE_TEST_CASE(protocol_block_in_31800__handle_chase__purge_without_wor

BOOST_FIXTURE_TEST_CASE(protocol_block_in_31800__handle_chase__split_single__not_stopped, chaser_check_candidate_setup_fixture)
{
// The channel is given one of the two candidates (the other is held).
const auto work = get_hashes();
BOOST_REQUIRE(!put_hashes(chaser_check::split(work.map)));
BOOST_REQUIRE(handshake(peer_services));
receive(get_data::command);
subscribe();
Expand Down
193 changes: 193 additions & 0 deletions test/chasers/chaser_transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,199 @@ BOOST_FIXTURE_TEST_CASE(chaser_transaction__submit_compact__stored_unpooled_tx__

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(chaser_transaction_scan_tests)

// BIP352 send_and_receive_test_vectors.json: "Simple send: two inputs".
static chain::input to_input(const hash_digest& hash, const data_chunk& script,
const data_chunk& prevout) NOEXCEPT
{
chain::input in{ { hash, 0 }, { script, false }, {}, max_uint32 };
const chain::script prevout_script{ prevout, false };
in.prevout = to_shared<chain::output>(0u, prevout_script);
return in;
}

static const chain::transaction simple_send
{
2u,
chain::inputs
{
to_input
(
base16_hash("f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16"),
base16_chunk("483046022100ad79e6801dd9a8727f342f31c71c4912866f59dc6e7981878e92c5844a0ce929022100fb0d2393e813968648b9753b7e9871d90ab3d815ebf91820d704b19f4ed224d621025a1e61f898173040e20616d43e9f496fba90338a39faa1ed98fcbaeee4dd9be5"),
base16_chunk("76a91419c2f3ae0ca3b642bd3e49598b8da89f50c1416188ac")
),
to_input
(
base16_hash("a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d"),
base16_chunk("48304602210086783ded73e961037e77d49d9deee4edc2b23136e9728d56e4491c80015c3a63022100fda4c0f21ea18de29edbce57f7134d613e044ee150a89e2e64700de2d4e83d4e2103bd85685d03d111699b15d046319febe77f8de5286e9e512703cdee1bf3be3792"),
base16_chunk("76a914d9317c66f54ff0a152ec50b1d19c25be50c8e15988ac")
)
},
chain::outputs
{
{ 0u, chain::script{ base16_chunk("51203e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1"), false } }
},
0u
};

// Mainnet block 1 confirmed (coinbase link 1), scan rows linked 1 and 5.
static bool stored_scan(node::query& query) NOEXCEPT
{
const auto& block1 = p2p_compact_setup_fixture::block1();
const database::context context1{ 0, 1, 1231006505 };
const auto work1 = block1.header().proof() * 2u;
return query.set(block1, context1, work1, false, false)
&& query.push_confirmed(1, true)
&& query.set_silent(1, simple_send)
&& query.set_silent(5, simple_send);
}

struct chaser_transaction_scan_setup_fixture
: chaser_transaction_setup_fixture
{
inline chaser_transaction_scan_setup_fixture(bool relay, bool current,
const initializer& setup=stored_scan)
: chaser_transaction_setup_fixture([=](configuration& config)
{
config.network.enable_relay = relay;
config.node.currency_window_minutes = current ? 0 : 1440;
config.node.silent_start_height = 0;
config.database.initialize(config.bitcoin, false, 0);
}, setup)
{
}

bool mapped(const database::header_link& link)
{
using namespace std::chrono;
const auto deadline = steady_clock::now() + seconds(10);
while (steady_clock::now() < deadline)
{
if (!query_.get_scan_start(link).is_terminal())
return true;

std::this_thread::sleep_for(milliseconds(10));
}

return false;
}

};

struct scan_current_fixture
: chaser_transaction_scan_setup_fixture
{
inline scan_current_fixture()
: chaser_transaction_scan_setup_fixture(false, true)
{
}
};

struct scan_pooling_fixture
: chaser_transaction_scan_setup_fixture
{
inline scan_pooling_fixture()
: chaser_transaction_scan_setup_fixture(true, true)
{
}
};

struct scan_stale_fixture
: chaser_transaction_scan_setup_fixture
{
inline scan_stale_fixture()
: chaser_transaction_scan_setup_fixture(false, false)
{
}
};

struct scan_complete_fixture
: chaser_transaction_scan_setup_fixture
{
inline scan_complete_fixture()
: chaser_transaction_scan_setup_fixture(false, true, [](node::query& query)
{
return stored_scan(query)
&& query.set_scan_start(0, 42)
&& query.set_scan_start(1, 43);
})
{
}
};

struct scan_partial_fixture
: chaser_transaction_scan_setup_fixture
{
inline scan_partial_fixture()
: chaser_transaction_scan_setup_fixture(false, true, [](node::query& query)
{
return stored_scan(query) && query.set_scan_start(1, 43);
})
{
}
};

struct scan_unextended_fixture
: chaser_transaction_scan_setup_fixture
{
inline scan_unextended_fixture()
: chaser_transaction_scan_setup_fixture(false, true, [](node::query& query)
{
return stored_scan(query) && query.set_scan_start(0, 0);
})
{
}
};

BOOST_FIXTURE_TEST_CASE(chaser_transaction__scan__current_not_pooling__mapped, scan_current_fixture)
{
BOOST_REQUIRE(mapped(0));
BOOST_REQUIRE(!query_.is_pooling());
BOOST_REQUIRE_EQUAL(query_.get_scan_frontier(), 0u);
BOOST_REQUIRE_EQUAL(query_.get_scan_start(0), 0u);
BOOST_REQUIRE_EQUAL(query_.get_scan_start(1), 1u);
}

BOOST_FIXTURE_TEST_CASE(chaser_transaction__scan__current_pooling__mapped_and_latched, scan_pooling_fixture)
{
BOOST_REQUIRE(mapped(0));
BOOST_REQUIRE(query_.is_pooling());
BOOST_REQUIRE_EQUAL(query_.get_scan_frontier(), 2u);
BOOST_REQUIRE_EQUAL(query_.get_latch_tx(), 2u);
BOOST_REQUIRE_EQUAL(query_.get_scan_start(0), 0u);
BOOST_REQUIRE_EQUAL(query_.get_scan_start(1), 1u);
}

BOOST_FIXTURE_TEST_CASE(chaser_transaction__scan__not_current__unmapped, scan_stale_fixture)
{
BOOST_REQUIRE(query_.get_scan_start(0).is_terminal());
BOOST_REQUIRE(query_.get_scan_start(1).is_terminal());
}

BOOST_FIXTURE_TEST_CASE(chaser_transaction__scan__complete_map__unchanged, scan_complete_fixture)
{
BOOST_REQUIRE_EQUAL(query_.get_scan_start(0), 42u);
BOOST_REQUIRE_EQUAL(query_.get_scan_start(1), 43u);
}

BOOST_FIXTURE_TEST_CASE(chaser_transaction__scan__partial_map__remapped, scan_partial_fixture)
{
BOOST_REQUIRE(mapped(0));
BOOST_REQUIRE_EQUAL(query_.get_scan_start(0), 0u);
BOOST_REQUIRE_EQUAL(query_.get_scan_start(1), 1u);
}

BOOST_FIXTURE_TEST_CASE(chaser_transaction__scan__unmapped_top__extended, scan_unextended_fixture)
{
BOOST_REQUIRE(mapped(1));
BOOST_REQUIRE_EQUAL(query_.get_scan_start(0), 0u);
BOOST_REQUIRE_EQUAL(query_.get_scan_start(1), 1u);
}

BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(protocol_transaction_tests)

// protocol_transaction_in
Expand Down
40 changes: 21 additions & 19 deletions test/functional/p2p_setup_fixture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,15 @@ using namespace bc::network::messages::peer;

BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)

p2p_setup_fixture::p2p_setup_fixture(const initializer& setup,
const configurator& configure)
: config_{ chain::selection::mainnet },
store_
{
[&]() NOEXCEPT -> const database::settings&
{
config_.database.path = TEST_DIRECTORY;
return config_.database;
}()
},
query_{ store_ },
node_{ query_, config_, log_ }
// The store and the chasers copy settings at construction, so configuration
// precedes them.
configuration p2p_setup_fixture::configured(const configurator& configure)
{
test::clear(test::directory);

auto& network_settings = config_.network;
auto& node_settings = config_.node;
configuration config{ chain::selection::mainnet };
auto& network_settings = config.network;
auto& node_settings = config.node;

config.database.path = TEST_DIRECTORY;
network_settings.path = TEST_DIRECTORY;
network_settings.inbound.connections = 1;
network_settings.inbound.binds.clear();
Expand All @@ -62,7 +52,19 @@ p2p_setup_fixture::p2p_setup_fixture(const initializer& setup,

// Apply test-specific configuration overrides.
if (configure)
configure(config_);
configure(config);

return config;
}

p2p_setup_fixture::p2p_setup_fixture(const initializer& setup,
const configurator& configure)
: config_{ configured(configure) },
store_{ config_.database },
query_{ store_ },
node_{ query_, config_, log_ }
{
test::clear(test::directory);

// Create and populate the store.
auto ec = store_.create([](auto, auto) {});
Expand Down Expand Up @@ -93,7 +95,7 @@ p2p_setup_fixture::p2p_setup_fixture(const initializer& setup,
// Block until the node is running.
ec = running.get_future().get();
BOOST_REQUIRE_MESSAGE(!ec, ec.message());
socket_.connect(network_settings.inbound.binds.back().to_endpoint());
socket_.connect(config_.network.inbound.binds.back().to_endpoint());
}

p2p_setup_fixture::~p2p_setup_fixture()
Expand Down
2 changes: 2 additions & 0 deletions test/functional/p2p_setup_fixture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ struct p2p_setup_fixture
}

protected:
static configuration configured(const configurator& configure);

struct subscription
{
std::mutex mutex{};
Expand Down
Loading