View in context in the libbitcoin Slack #general mirror.
.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)