Skip to content

Adapt to new libff multiexp interface & use faster methods #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jul 27, 2017
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
32 changes: 20 additions & 12 deletions libsnark/common/data_structures/sparse_vector.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@

#include <numeric>

#ifdef MULTICORE
#include <omp.h>
#endif

#include <libff/algebra/scalar_multiplication/multiexp.hpp>

namespace libsnark {
Expand Down Expand Up @@ -180,9 +184,11 @@ std::pair<T, sparse_vector<T> > sparse_vector<T>::accumulate(const typename std:
const typename std::vector<FieldT>::const_iterator &it_end,
const size_t offset) const
{
// TODO: does not really belong here.
#ifdef MULTICORE
const size_t chunks = omp_get_max_threads(); // to override, set OMP_NUM_THREADS env var or call omp_set_num_threads()
#else
const size_t chunks = 1;
const bool use_multiexp = true;
#endif

T accumulated_value = T::zero();
sparse_vector<T> resulting_vector;
Expand Down Expand Up @@ -215,11 +221,12 @@ std::pair<T, sparse_vector<T> > sparse_vector<T>::accumulate(const typename std:
#ifdef DEBUG
libff::print_indent(); printf("doing multiexp for w_%zu ... w_%zu\n", indices[first_pos], indices[last_pos]);
#endif
accumulated_value = accumulated_value + libff::multi_exp<T, FieldT>(values.begin() + first_pos,
values.begin() + last_pos + 1,
it_begin + (indices[first_pos] - offset),
it_begin + (indices[last_pos] - offset) + 1,
chunks, use_multiexp);
accumulated_value = accumulated_value + libff::multi_exp<T, FieldT, libff::multi_exp_method_bos_coster>(
values.begin() + first_pos,
values.begin() + last_pos + 1,
it_begin + (indices[first_pos] - offset),
it_begin + (indices[last_pos] - offset) + 1,
chunks);
}
}
else
Expand Down Expand Up @@ -250,11 +257,12 @@ std::pair<T, sparse_vector<T> > sparse_vector<T>::accumulate(const typename std:
#ifdef DEBUG
libff::print_indent(); printf("doing multiexp for w_%zu ... w_%zu\n", indices[first_pos], indices[last_pos]);
#endif
accumulated_value = accumulated_value + libff::multi_exp<T, FieldT>(values.begin() + first_pos,
values.begin() + last_pos + 1,
it_begin + (indices[first_pos] - offset),
it_begin + (indices[last_pos] - offset) + 1,
chunks, use_multiexp);
accumulated_value = accumulated_value + libff::multi_exp<T, FieldT, libff::multi_exp_method_bos_coster>(
values.begin() + first_pos,
values.begin() + last_pos + 1,
it_begin + (indices[first_pos] - offset),
it_begin + (indices[last_pos] - offset) + 1,
chunks);
}

return std::make_pair(accumulated_value, resulting_vector);
Expand Down
10 changes: 4 additions & 6 deletions libsnark/knowledge_commitment/kc_multiexp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
Will probably go away in more general exp refactoring.
*/

#include <libff/algebra/scalar_multiplication/multiexp.hpp>

#include <libsnark/knowledge_commitment/knowledge_commitment.hpp>

namespace libsnark {
Expand All @@ -25,17 +27,13 @@ template<typename T1, typename T2, mp_size_t n>
knowledge_commitment<T1,T2> opt_window_wnaf_exp(const knowledge_commitment<T1,T2> &base,
const libff::bigint<n> &scalar, const size_t scalar_bits);

template<typename T1, typename T2, typename FieldT>
template<typename T1, typename T2, typename FieldT, libff::multi_exp_method Method>
knowledge_commitment<T1, T2> kc_multi_exp_with_mixed_addition(const knowledge_commitment_vector<T1, T2> &vec,
const size_t min_idx,
const size_t max_idx,
typename std::vector<FieldT>::const_iterator scalar_start,
typename std::vector<FieldT>::const_iterator scalar_end,
const size_t chunks,
const bool use_multiexp=false);

template<typename T1, typename T2>
void kc_batch_to_special(std::vector<knowledge_commitment<T1, T2> > &vec);
const size_t chunks);

template<typename T1, typename T2, typename FieldT>
knowledge_commitment_vector<T1, T2> kc_batch_exp(const size_t scalar_size,
Expand Down
79 changes: 4 additions & 75 deletions libsnark/knowledge_commitment/kc_multiexp.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ knowledge_commitment<T1,T2> opt_window_wnaf_exp(const knowledge_commitment<T1,T2
opt_window_wnaf_exp(base.h, scalar, scalar_bits));
}

template<typename T1, typename T2, typename FieldT>
template<typename T1, typename T2, typename FieldT, libff::multi_exp_method Method>
knowledge_commitment<T1, T2> kc_multi_exp_with_mixed_addition(const knowledge_commitment_vector<T1, T2> &vec,
const size_t min_idx,
const size_t max_idx,
typename std::vector<FieldT>::const_iterator scalar_start,
typename std::vector<FieldT>::const_iterator scalar_end,
const size_t chunks,
const bool use_multiexp)
const size_t chunks)
{
libff::enter_block("Process scalar vector");
auto index_it = std::lower_bound(vec.indices.begin(), vec.indices.end(), min_idx);
Expand Down Expand Up @@ -86,77 +85,7 @@ knowledge_commitment<T1, T2> kc_multi_exp_with_mixed_addition(const knowledge_co
libff::print_indent(); printf("* Elements of w remaining: %zu (%0.2f%%)\n", num_other, 100.*num_other/(num_skip+num_add+num_other));
libff::leave_block("Process scalar vector");

return acc + libff::multi_exp<knowledge_commitment<T1, T2>, FieldT>(g.begin(), g.end(), p.begin(), p.end(), chunks, use_multiexp);
}

template<typename T1, typename T2>
void kc_batch_to_special(std::vector<knowledge_commitment<T1, T2> > &vec)
{
libff::enter_block("Batch-convert knowledge-commitments to special form");

std::vector<T1> g_vec;
g_vec.reserve(vec.size());

for (size_t i = 0; i < vec.size(); ++i)
{
if (!vec[i].g.is_zero())
{
g_vec.emplace_back(vec[i].g);
}
}

libff::batch_to_special_all_non_zeros<T1>(g_vec);
auto g_it = g_vec.begin();
T1 T1_zero_special = T1::zero();
T1_zero_special.to_special();

for (size_t i = 0; i < vec.size(); ++i)
{
if (!vec[i].g.is_zero())
{
vec[i].g = *g_it;
++g_it;
}
else
{
vec[i].g = T1_zero_special;
}
}

g_vec.clear();

std::vector<T2> h_vec;
h_vec.reserve(vec.size());

for (size_t i = 0; i < vec.size(); ++i)
{
if (!vec[i].h.is_zero())
{
h_vec.emplace_back(vec[i].h);
}
}

libff::batch_to_special_all_non_zeros<T2>(h_vec);
auto h_it = h_vec.begin();
T2 T2_zero_special = T2::zero();
T2_zero_special.to_special();

for (size_t i = 0; i < vec.size(); ++i)
{
if (!vec[i].h.is_zero())
{
vec[i].h = *h_it;
++h_it;
}
else
{
vec[i].h = T2_zero_special;
}
}

g_vec.clear();

libff::leave_block("Batch-convert knowledge-commitments to special form");
return acc + libff::multi_exp<knowledge_commitment<T1, T2>, FieldT, Method>(g.begin(), g.end(), p.begin(), p.end(), chunks);
}

template<typename T1, typename T2, typename FieldT>
Expand Down Expand Up @@ -249,7 +178,7 @@ knowledge_commitment_vector<T1, T2> kc_batch_exp(const size_t scalar_size,
tmp[i] = kc_batch_exp_internal<T1, T2, FieldT>(scalar_size, T1_window, T2_window, T1_table, T2_table, T1_coeff, T2_coeff, v,
chunk_pos[i], chunk_pos[i+1], i == num_chunks - 1 ? last_chunk : chunk_size);
#ifdef USE_MIXED_ADDITION
kc_batch_to_special<T1, T2>(tmp[i].values);
libff::batch_to_special<knowledge_commitment<T1, T2>>(tmp[i].values);
#endif
}

Expand Down
8 changes: 8 additions & 0 deletions libsnark/knowledge_commitment/knowledge_commitment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ struct knowledge_commitment {
knowledge_commitment<T1,T2>& operator=(const knowledge_commitment<T1,T2> &other) = default;
knowledge_commitment<T1,T2>& operator=(knowledge_commitment<T1,T2> &&other) = default;
knowledge_commitment<T1,T2> operator+(const knowledge_commitment<T1, T2> &other) const;
knowledge_commitment<T1,T2> mixed_add(const knowledge_commitment<T1, T2> &other) const;
knowledge_commitment<T1,T2> dbl() const;

void to_special();
bool is_special() const;

bool is_zero() const;
bool operator==(const knowledge_commitment<T1,T2> &other) const;
Expand All @@ -56,6 +61,9 @@ struct knowledge_commitment {
void print() const;

static size_t size_in_bits();

static void batch_to_special_all_non_zeros(
std::vector<knowledge_commitment<T1,T2> > &vec);
};

template<typename T1, typename T2, mp_size_t m>
Expand Down
101 changes: 101 additions & 0 deletions libsnark/knowledge_commitment/knowledge_commitment.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,33 @@ knowledge_commitment<T1,T2> knowledge_commitment<T1,T2>::operator+(const knowled
this->h + other.h);
}

template<typename T1, typename T2>
knowledge_commitment<T1,T2> knowledge_commitment<T1,T2>::mixed_add(const knowledge_commitment<T1,T2> &other) const
{
return knowledge_commitment<T1,T2>(this->g.mixed_add(other.g),
this->h.mixed_add(other.h));
}

template<typename T1, typename T2>
knowledge_commitment<T1,T2> knowledge_commitment<T1,T2>::dbl() const
{
return knowledge_commitment<T1,T2>(this->g.dbl(),
this->h.dbl());
}

template<typename T1, typename T2>
void knowledge_commitment<T1,T2>::to_special()
{
this->g.to_special();
this->h.to_special();
}

template<typename T1, typename T2>
bool knowledge_commitment<T1,T2>::is_special() const
{
return this->g->is_special() && this->h->is_special();
}

template<typename T1, typename T2>
bool knowledge_commitment<T1,T2>::is_zero() const
{
Expand Down Expand Up @@ -106,6 +133,80 @@ std::istream& operator>>(std::istream& in, knowledge_commitment<T1,T2> &kc)
return in;
}

template<typename T1, typename T2>
void knowledge_commitment<T1,T2>::batch_to_special_all_non_zeros(
std::vector<knowledge_commitment<T1,T2> > &vec)
{
// it is guaranteed that every vec[i] is non-zero,
// but, for any i, *one* of vec[i].g and vec[i].h might still be zero,
// so we still have to handle zeros separately

// we separately process g's first, then h's
// to lower memory consumption
std::vector<T1> g_vec;
g_vec.reserve(vec.size());

for (size_t i = 0; i < vec.size(); ++i)
{
if (!vec[i].g.is_zero())
{
g_vec.emplace_back(vec[i].g);
}
}

T1::batch_to_special_all_non_zeros(g_vec);
auto g_it = g_vec.begin();
T1 T1_zero_special = T1::zero();
T1_zero_special.to_special();

for (size_t i = 0; i < vec.size(); ++i)
{
if (!vec[i].g.is_zero())
{
vec[i].g = *g_it;
++g_it;
}
else
{
vec[i].g = T1_zero_special;
}
}

g_vec.clear();

// exactly the same thing, but for h:
std::vector<T2> h_vec;
h_vec.reserve(vec.size());

for (size_t i = 0; i < vec.size(); ++i)
{
if (!vec[i].h.is_zero())
{
h_vec.emplace_back(vec[i].h);
}
}

T2::batch_to_special_all_non_zeros(h_vec);
auto h_it = h_vec.begin();
T2 T2_zero_special = T2::zero();
T2_zero_special.to_special();

for (size_t i = 0; i < vec.size(); ++i)
{
if (!vec[i].h.is_zero())
{
vec[i].h = *h_it;
++h_it;
}
else
{
vec[i].h = T2_zero_special;
}
}

h_vec.clear();
}

} // libsnark

#endif // KNOWLEDGE_COMMITMENT_TCC_
24 changes: 16 additions & 8 deletions libsnark/relations/arithmetic_programs/qap/qap.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -242,14 +242,22 @@ bool qap_instance_evaluation<FieldT>::is_satisfied(const qap_witness<FieldT> &wi
FieldT ans_C = this->Ct[0] + witness.d3*this->Zt;
FieldT ans_H = FieldT::zero();

ans_A = ans_A + libff::naive_plain_exp<FieldT, FieldT>(this->At.begin()+1, this->At.begin()+1+this->num_variables(),
witness.coefficients_for_ABCs.begin(), witness.coefficients_for_ABCs.begin()+this->num_variables());
ans_B = ans_B + libff::naive_plain_exp<FieldT, FieldT>(this->Bt.begin()+1, this->Bt.begin()+1+this->num_variables(),
witness.coefficients_for_ABCs.begin(), witness.coefficients_for_ABCs.begin()+this->num_variables());
ans_C = ans_C + libff::naive_plain_exp<FieldT, FieldT>(this->Ct.begin()+1, this->Ct.begin()+1+this->num_variables(),
witness.coefficients_for_ABCs.begin(), witness.coefficients_for_ABCs.begin()+this->num_variables());
ans_H = ans_H + libff::naive_plain_exp<FieldT, FieldT>(this->Ht.begin(), this->Ht.begin()+this->degree()+1,
witness.coefficients_for_H.begin(), witness.coefficients_for_H.begin()+this->degree()+1);
ans_A = ans_A + libff::inner_product<FieldT>(this->At.begin()+1,
this->At.begin()+1+this->num_variables(),
witness.coefficients_for_ABCs.begin(),
witness.coefficients_for_ABCs.begin()+this->num_variables());
ans_B = ans_B + libff::inner_product<FieldT>(this->Bt.begin()+1,
this->Bt.begin()+1+this->num_variables(),
witness.coefficients_for_ABCs.begin(),
witness.coefficients_for_ABCs.begin()+this->num_variables());
ans_C = ans_C + libff::inner_product<FieldT>(this->Ct.begin()+1,
this->Ct.begin()+1+this->num_variables(),
witness.coefficients_for_ABCs.begin(),
witness.coefficients_for_ABCs.begin()+this->num_variables());
ans_H = ans_H + libff::inner_product<FieldT>(this->Ht.begin(),
this->Ht.begin()+this->degree()+1,
witness.coefficients_for_H.begin(),
witness.coefficients_for_H.begin()+this->degree()+1);

if (ans_A * ans_B - ans_C != ans_H * this->Zt)
{
Expand Down
12 changes: 8 additions & 4 deletions libsnark/relations/arithmetic_programs/ssp/ssp.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,14 @@ bool ssp_instance_evaluation<FieldT>::is_satisfied(const ssp_witness<FieldT> &wi
FieldT ans_V = this->Vt[0] + witness.d*this->Zt;
FieldT ans_H = FieldT::zero();

ans_V = ans_V + libff::naive_plain_exp<FieldT, FieldT>(this->Vt.begin()+1, this->Vt.begin()+1+this->num_variables(),
witness.coefficients_for_Vs.begin(), witness.coefficients_for_Vs.begin()+this->num_variables());
ans_H = ans_H + libff::naive_plain_exp<FieldT, FieldT>(this->Ht.begin(), this->Ht.begin()+this->degree()+1,
witness.coefficients_for_H.begin(), witness.coefficients_for_H.begin()+this->degree()+1);
ans_V = ans_V + libff::inner_product<FieldT>(this->Vt.begin()+1,
this->Vt.begin()+1+this->num_variables(),
witness.coefficients_for_Vs.begin(),
witness.coefficients_for_Vs.begin()+this->num_variables());
ans_H = ans_H + libff::inner_product<FieldT>(this->Ht.begin(),
this->Ht.begin()+this->degree()+1,
witness.coefficients_for_H.begin(),
witness.coefficients_for_H.begin()+this->degree()+1);

if (ans_V.squared() - FieldT::one() != ans_H * this->Zt)
{
Expand Down
Loading