diff --git a/data/bn.cfg b/data/bn.cfg index aad895963..c04f6576e 100644 --- a/data/bn.cfg +++ b/data/bn.cfg @@ -73,6 +73,14 @@ filter_tx_buckets = filter_tx_rate = # The minimum allocation of the filter_tx table body, defaults to '1'. filter_tx_size = +# The number of buckets in the silent table head, defaults to '0' (0 disables). +silent_buckets = +# The percentage expansion of the silent table body, defaults to '5'. +silent_rate = +# The minimum allocation of the silent table body, defaults to '1'. +silent_size = +# The first height indexed by the silent table, defaults to the bip341 activation height. +silent_start_height = # The number of buckets in the header table head, defaults to '386364'. header_buckets = # The percentage expansion of the header table body, defaults to '5'. diff --git a/include/bitcoin/node/chase.hpp b/include/bitcoin/node/chase.hpp index 891be3987..30533cc4a 100644 --- a/include/bitcoin/node/chase.hpp +++ b/include/bitcoin/node/chase.hpp @@ -145,6 +145,10 @@ enum class chase /// Issued by 'confirm' and handled by 'transaction'. reorganized, + /// Silent payment prevout summaries indexed for confirmed block (header_t). + /// Issued by 'confirm' and handled by protocol subscribers. + silent_indexed, + /// Mining. /// ----------------------------------------------------------------------- diff --git a/include/bitcoin/node/chasers/chaser_validate.hpp b/include/bitcoin/node/chasers/chaser_validate.hpp index 5ba698d28..99067cc7e 100644 --- a/include/bitcoin/node/chasers/chaser_validate.hpp +++ b/include/bitcoin/node/chasers/chaser_validate.hpp @@ -90,6 +90,7 @@ class BCN_API chaser_validate const bool node_witness_; const bool defer_; const bool filter_; + const bool silent_; }; } // namespace node diff --git a/include/bitcoin/node/error.hpp b/include/bitcoin/node/error.hpp index 065e6c94f..57266fb3d 100644 --- a/include/bitcoin/node/error.hpp +++ b/include/bitcoin/node/error.hpp @@ -91,6 +91,7 @@ enum error_t : uint8_t validate6, validate7, validate8, + validate9, confirm1, confirm2, confirm3, diff --git a/src/chasers/chaser_confirm.cpp b/src/chasers/chaser_confirm.cpp index 86df17a28..11b707232 100644 --- a/src/chasers/chaser_confirm.cpp +++ b/src/chasers/chaser_confirm.cpp @@ -388,6 +388,11 @@ bool chaser_confirm::set_organized(const header_link& link, } #endif // !NDEBUG + const auto silent = query.silent_enabled() && + confirmed_height >= query.silent_start_height(); + if (silent && !query.is_silent_indexed(link)) + return false; + // Checkpointed blocks are set strong by archiver. if (!query.push_confirmed(link, !is_under_checkpoint(confirmed_height))) return false; @@ -396,6 +401,9 @@ bool chaser_confirm::set_organized(const header_link& link, fire(events::block_organized, confirmed_height); LOGV("Block organized: " << confirmed_height); + if (silent) + notify(error::success, chase::silent_indexed, link); + announce(link, confirmed_height); return true; } diff --git a/src/chasers/chaser_validate.cpp b/src/chasers/chaser_validate.cpp index f73a19be6..26f115f53 100644 --- a/src/chasers/chaser_validate.cpp +++ b/src/chasers/chaser_validate.cpp @@ -45,7 +45,11 @@ chaser_validate::chaser_validate(full_node& node) NOEXCEPT maximum_backlog_(node.node_settings().maximum_concurrency_()), node_witness_(node.network_settings().witness_node()), defer_(node.node_settings().defer_validation), - filter_(!defer_ && node.archive().filter_enabled()) + filter_(!defer_ && node.archive().filter_enabled()), + silent_(!defer_ && node.network_settings().witness_node() && + node.node_settings().headers_first && + node.system_settings().forks.bip341 && + node.archive().silent_enabled()) { } @@ -160,13 +164,14 @@ void chaser_validate::do_bumped(height_t height) NOEXCEPT const auto bypass = defer_ || is_under_checkpoint(height) || query.is_milestone(link); + const auto silent = silent_ && height >= query.silent_start_height(); switch (ec.value()) { case database::error::unvalidated: case database::error::unknown_state: { - if (!bypass || filter_) + if (!bypass || filter_ || silent) post_block(link, bypass); else complete_block(error::success, link, height, true); @@ -175,7 +180,11 @@ void chaser_validate::do_bumped(height_t height) NOEXCEPT case database::error::block_valid: case database::error::block_confirmable: { - complete_block(error::success, link, height, true); + if (silent && !query.is_silent_indexed(link)) + post_block(link, true); + else + complete_block(error::success, link, height, true); + break; } case database::error::block_unconfirmable: @@ -254,7 +263,7 @@ code chaser_validate::populate(bool bypass, const chain::block& block, if (bypass) { - // Populating for filters only (no validation metadata required). + // Populating optional indexes only (no validation metadata required). block.populate(ctx); if (!query.populate_without_metadata(block)) return system::error::missing_previous_output; @@ -306,7 +315,10 @@ code chaser_validate::validate(bool bypass, const chain::block& block, if (!query.set_filter_body(link, block)) return error::validate7; - // Valid must be set after set_prevouts and set_filter_body. + if (silent_ && !query.set_silent(link, block)) + return error::validate9; + + // Valid must be set after optional block indexes. if (!bypass && !query.set_block_valid(link)) return error::validate8; @@ -334,7 +346,6 @@ void chaser_validate::complete_block(const code& ec, const header_link& link, return; } - // VALID BLOCK // Under deferral there is no state change, but downloads will stall unless // the window is closed out, so notify the check chaser of the increment. notify(ec, chase::valid, possible_wide_cast(height)); diff --git a/src/configuration.cpp b/src/configuration.cpp index 1cda25bc8..aef7d8ad3 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -31,6 +31,7 @@ configuration::configuration(system::chain::selection context) NOEXCEPT network(context), node(context) { + database.silent_start_height = bitcoin.bip9_bit2_active_checkpoint.height(); } } // namespace node diff --git a/src/error.cpp b/src/error.cpp index 894f823d1..db13c391a 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -81,6 +81,7 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) { validate6, "validate6" }, { validate7, "validate7" }, { validate8, "validate8" }, + { validate9, "validate9" }, { confirm1, "confirm1" }, { confirm2, "confirm2" }, { confirm3, "confirm3" }, diff --git a/test/configuration.cpp b/test/configuration.cpp index 6785e9895..497a78cc9 100644 --- a/test/configuration.cpp +++ b/test/configuration.cpp @@ -33,4 +33,12 @@ BOOST_AUTO_TEST_CASE(configuration__construct1__none_context__expected) BOOST_REQUIRE_EQUAL(instance.bitcoin.first_version, 1_u32); } +BOOST_AUTO_TEST_CASE(configuration__construct1__mainnet_silent_start__expected) +{ + const node::configuration instance(chain::selection::mainnet); + const auto height = instance.bitcoin.bip9_bit2_active_checkpoint.height(); + + BOOST_REQUIRE_EQUAL(instance.database.silent_start_height, height); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/test/error.cpp b/test/error.cpp index 525397751..ebf705330 100644 --- a/test/error.cpp +++ b/test/error.cpp @@ -232,7 +232,7 @@ BOOST_AUTO_TEST_CASE(error_t__code__organize1__true_expected_message) BOOST_REQUIRE_EQUAL(ec.message(), "organize1"); } -// TODO: validate2-validate6 +// TODO: validate2-validate9 BOOST_AUTO_TEST_CASE(error_t__code__validate1__true_expected_message) { constexpr auto value = error::validate1;