diff --git a/include/bitcoin/node/chasers/chaser_validate.hpp b/include/bitcoin/node/chasers/chaser_validate.hpp index 9c86fddc..d4b8191e 100644 --- a/include/bitcoin/node/chasers/chaser_validate.hpp +++ b/include/bitcoin/node/chasers/chaser_validate.hpp @@ -67,14 +67,14 @@ class BCN_API chaser_validate /// Validation. virtual void post_block(const header_link& link, bool bypass) NOEXCEPT; virtual void validate_block(const header_link& link, bool bypass) NOEXCEPT; - virtual code validate(bool& batched, bool& faulted, bool& capturing, - bool bypass, const system::chain::block& block, - const header_link& link, const system::chain::context& ctx) NOEXCEPT; + virtual code validate(bool& batched, bool& capturing, bool bypass, + const system::chain::block& block, const header_link& link, + const system::chain::context& ctx) NOEXCEPT; virtual code populate(bool bypass, const system::chain::block& block, const system::chain::context& ctx) NOEXCEPT; virtual void complete_block(const code& ec, const header_link& link, size_t height, bool bypass, bool batched=false, - bool faulted=false, bool capturing=false) NOEXCEPT; + bool capturing=false) NOEXCEPT; virtual void notify_block(const code& ec, size_t height, const header_link& link, bool bypass, bool startup=false) NOEXCEPT; @@ -94,9 +94,11 @@ class BCN_API chaser_validate private: static constexpr auto relaxed = std::memory_order_relaxed; + using schnorr_link = database::schnorr_link; + using schnorr_link_ptr = std::shared_ptr; using atomic_counter = std::atomic; using atomic_counter_ptr = std::shared_ptr; - using threshold = system::chain::threshold; + using cursor = system::chain::threshold::cursor; using missed = signatures::miss; // Capture handlers. @@ -109,11 +111,13 @@ class BCN_API chaser_validate const system::ec_xonly& point, const system::ec_signature& sign, const header_link& link) NOEXCEPT; bool do_multisig(const system::hash_digest& digest, - const system::ec_compresseds& points, - const system::ec_signatures& signs, const header_link& link, - const atomic_counter_ptr& sequence) NOEXCEPT; - bool do_threshold(const threshold& batch, - const header_link& link) NOEXCEPT; + const std::span& points, + const std::span& signs, + const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT; + bool do_threshold(const system::hash_digest& digest, + const system::ec_xonly& point, const system::ec_signature& sign, + const schnorr_link_ptr& fk_ptr, const header_link& link) NOEXCEPT; + cursor open_threshold(size_t rows, const header_link& link) NOEXCEPT; // Capture helpers. signatures get_capture(const header_link& link) NOEXCEPT; diff --git a/src/chasers/chaser_validate.cpp b/src/chasers/chaser_validate.cpp index 5687bc9c..491667c0 100644 --- a/src/chasers/chaser_validate.cpp +++ b/src/chasers/chaser_validate.cpp @@ -233,8 +233,7 @@ void chaser_validate::post_block(const header_link& link, // May be either concurrent or stranded. void chaser_validate::complete_block(const code& ec, const header_link& link, - size_t height, bool bypass, bool batched, bool faulted, - bool capturing) NOEXCEPT + size_t height, bool bypass, bool batched, bool capturing) NOEXCEPT { // Not stranded when called from validate_block. if (is_zero(validate_backlog_.load()) && !stranded()) @@ -267,8 +266,7 @@ void chaser_validate::complete_block(const code& ec, const header_link& link, // Batch jobs (all posting from unstranded). // ------------------------------------------------------------------------ - // Faulted implies disk full prevented threshold batch writes. - if (closed() || !batch_enabled_ || faulted) + if (closed() || !batch_enabled_) return; // Queue block and process batch if ready. diff --git a/src/chasers/chaser_validate_batch.cpp b/src/chasers/chaser_validate_batch.cpp index f1afce5b..dec1f32a 100644 --- a/src/chasers/chaser_validate_batch.cpp +++ b/src/chasers/chaser_validate_batch.cpp @@ -58,8 +58,8 @@ code chaser_validate::start_batch() NOEXCEPT return do_process_batch(true); } -// Shutdown drains batched_ to block prevalid states, recovered on startup. -// Snapshot restoration purges batch backlog as the tables are not append-only. +// Shutdown drains batched_ to prevalid table, which is recovered on startup. +// Snapshot restoration purges sigs and prevalids as these are not append-only. void chaser_validate::close_batch() NOEXCEPT { BC_ASSERT(stranded()); @@ -130,7 +130,7 @@ void chaser_validate::process_batch(bool residual) NOEXCEPT } // ======================================================================== - // Log outside of lock, oand nly when batch executes (non-verbose). + // Log outside of lock, and only when batch executes (non-verbose). log_captures(); } diff --git a/src/chasers/chaser_validate_capture.cpp b/src/chasers/chaser_validate_capture.cpp index d9e47bec..77dadaac 100644 --- a/src/chasers/chaser_validate_capture.cpp +++ b/src/chasers/chaser_validate_capture.cpp @@ -88,7 +88,8 @@ bool chaser_validate::do_schnorr(const hash_digest& digest, } bool chaser_validate::do_multisig(const hash_digest& digest, - const ec_compresseds& points, const ec_signatures& signs, + const std::span& points, + const std::span& signs, const header_link& link, const atomic_counter_ptr& sequence) NOEXCEPT { multisig_ += points.size(); @@ -100,15 +101,31 @@ bool chaser_validate::do_multisig(const hash_digest& digest, return set; } -bool chaser_validate::do_threshold(const threshold& batch, - const header_link& link) NOEXCEPT +bool chaser_validate::do_threshold(const hash_digest& digest, + const ec_xonly& point, const ec_signature& sign, + const schnorr_link_ptr& fk_ptr, const header_link& link) NOEXCEPT { - threshold_ += batch.tuples.size(); - const auto set = archive().set_signatures(batch, link); + auto set = archive().set_signature((*fk_ptr)++, digest, point, sign, link); if (!set) fault(error::batch8); return set; } +chaser_validate::cursor chaser_validate::open_threshold(size_t rows, + const header_link& link) NOEXCEPT +{ + auto first = archive().allocate_signatures(rows); + const auto fk = emplace_shared(first); + if (fk->is_terminal()) + return {}; + + threshold_ += rows; + return + { + .put = BIND_THIS(do_threshold, _1, _2, _3, fk, link), + .rows = rows + }; +} + // Capture helpers. // ---------------------------------------------------------------------------- // private @@ -127,7 +144,7 @@ signatures chaser_validate::get_capture(const header_link& link) NOEXCEPT .ecdsa = BIND_THIS(do_ecdsa, _1, _2, _3, link, sequence), .schnorr = BIND_THIS(do_schnorr, _1, _2, _3, link), .multisig = BIND_THIS(do_multisig, _1, _2, _3, link, sequence), - .threshold = BIND_THIS(do_threshold, _1, link) + .threshold = BIND_THIS(open_threshold, _1, link) }; } diff --git a/src/chasers/chaser_validate_parallel.cpp b/src/chasers/chaser_validate_parallel.cpp index f28578a7..2dd75740 100644 --- a/src/chasers/chaser_validate_parallel.cpp +++ b/src/chasers/chaser_validate_parallel.cpp @@ -38,7 +38,7 @@ void chaser_validate::validate_block(const header_link& link, code ec{}; chain::context ctx{}; - bool batched{}, faulted{}, capturing{}; + bool batched{}, capturing{}; auto& query = archive(); // TODO: implement allocator parameter resulting in full allocation to @@ -58,7 +58,7 @@ void chaser_validate::validate_block(const header_link& link, if (!query.set_block_unconfirmable(link)) ec = error::validate4; } - else if ((ec = validate(batched, faulted, capturing, bypass, *block, link, + else if ((ec = validate(batched, capturing, bypass, *block, link, ctx))) { if (!query.set_block_unconfirmable(link)) @@ -66,7 +66,7 @@ void chaser_validate::validate_block(const header_link& link, } --validate_backlog_; - complete_block(ec, link, ctx.height, bypass, batched, faulted, capturing); + complete_block(ec, link, ctx.height, bypass, batched, capturing); } // helpers @@ -99,8 +99,8 @@ code chaser_validate::populate(bool bypass, const chain::block& block, return error::success; } -code chaser_validate::validate(bool& batched, bool& faulted, bool& capturing, - bool bypass, const chain::block& block, const header_link& link, +code chaser_validate::validate(bool& batched, bool& capturing, bool bypass, + const chain::block& block, const header_link& link, const chain::context& ctx) NOEXCEPT { auto& query = archive(); @@ -127,36 +127,29 @@ code chaser_validate::validate(bool& batched, bool& faulted, bool& capturing, if (capturing) lock.lock(); // Sequentially connect block with signature capture (if enabled). - // There is not stop during connect, so shutdown will wait on the - // completion (block consistency) of all signature captures. But - // the faulted state of batch is not persisted (because disk full). + // There is no stop during connect, so shutdown will wait on the + // completion (block consistency) of all signature captures. if ((ec = block.connect(ctx, capture))) return ec; // At least one signature batch was attempted (defer completion). batched = capture.batched; - - // Threshold batch commit failed, block otherwise passed (retry). - faulted = capture.faulted; } - // ================================================================ + // ==================================================================== // Prevouts optimize confirmation. - // Block will be retried if batch is faulted. - if (!faulted && !query.set_prevouts(link, block)) + if (!query.set_prevouts(link, block)) return error::validate6; } - // Block will be retried if batch is faulted. - if (!faulted && !query.set_filter_body(link, block)) + if (!query.set_filter_body(link, block)) return error::validate7; - // Block will be retried if batch is faulted. - if (!faulted && (ctx.height >= silent_start_height_) && + if ((ctx.height >= silent_start_height_) && !query.set_silent(link, block)) return error::validate8; - // Defer block state change when batched (or faulted). + // Defer block state change when batched. // Valid must be set after set_prevouts, set_filter_body, and set_silent. if (!batched && !bypass && !query.set_block_valid(link)) return error::validate9;