Bitcoin full node and query server

Jun 11, 2026

View in context in the libbitcoin Slack #general mirror.

evoskuil23:47
The unit tests are sufficient to show basic batch correctness, as these were previously written against the fallback implementation, which uses a c++17 parallel loop over the batch. That's now running against Ultrafast (based on the changed NuGet dependency selection via the vs2026 .props integration).
// batch_verify
// ----------------------------------------------------------------------------

#if defined(HAVE_ULTRAFAST)

template <typename Batch>
data_chunk batch_verify(const std::span<Batch>& batch, bool) NOEXCEPT
{
    // OOM is unrecoverable.
    static thread_local ufsecp::lbtc::Controller context{ UFSECP_LBTC_AUTO };
    if (!context.ok()) std::abort();

    const auto count = batch.size();
    data_chunk results(count);
    const auto out = results.data();
    const auto in = pointer_cast<const uint8_t>(batch.data());

    if constexpr (is_same_type<Batch, schnorr::batch>)
    {
        constexpr auto extra_size = sizeof(Batch) - (sizeof(hash_digest) +
            sizeof(ec_xonly) + sizeof(ec_signature));
        ufsecp_lbtc_verify_schnorr(context.get(), in, count, extra_size, out);
    }
    else
    {
        constexpr auto extra_size = sizeof(Batch) - (sizeof(hash_digest) +
            sizeof(ec_compressed) + sizeof(ec_signature));
        ufsecp_lbtc_verify_ecdsa(context.get(), in, count, extra_size, out);
    }

    return results;
}

#else

template <typename Batch>
data_chunk batch_verify(const std::span<Batch>& batch, bool turbo) NOEXCEPT
{
    // par_if doesn't throw.
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
    const auto policy = poolstl::execution::par_if(turbo);
    BC_POP_WARNING()

    // Used only to produce order for concurrency.
    std::vector<size_t> it(batch.size());
    std::iota(it.begin(), it.end(), zero);

    // Collect signature validation results as corresponding integer booleans.
    data_chunk results(batch.size());
    std::for_each(policy, it.cbegin(), it.cend(), [&](size_t row) NOEXCEPT
    {
        results.at(row) = to_int<uint8_t>(verify_signature(batch[row]));
    });

    return results;
}

#endif
(edited)