Original HUSH source code based on ZEC 1.0.8 . For historical purposes only!
https://hush.is
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
330 lines
8.5 KiB
330 lines
8.5 KiB
/** @file
|
|
*****************************************************************************
|
|
* @author This file is part of libsnark, developed by SCIPR Lab
|
|
* and contributors (see AUTHORS).
|
|
* @copyright MIT license (see LICENSE file)
|
|
*****************************************************************************/
|
|
|
|
#ifndef PB_VARIABLE_TCC_
|
|
#define PB_VARIABLE_TCC_
|
|
#include <cassert>
|
|
#include "gadgetlib1/protoboard.hpp"
|
|
#include "common/utils.hpp"
|
|
|
|
namespace libsnark {
|
|
|
|
template<typename FieldT>
|
|
void pb_variable<FieldT>::allocate(protoboard<FieldT> &pb, const std::string &annotation)
|
|
{
|
|
this->index = pb.allocate_var_index(annotation);
|
|
}
|
|
|
|
/* allocates pb_variable<FieldT> array in MSB->LSB order */
|
|
template<typename FieldT>
|
|
void pb_variable_array<FieldT>::allocate(protoboard<FieldT> &pb, const size_t n, const std::string &annotation_prefix)
|
|
{
|
|
#ifdef DEBUG
|
|
assert(annotation_prefix != "");
|
|
#endif
|
|
(*this).resize(n);
|
|
|
|
for (size_t i = 0; i < n; ++i)
|
|
{
|
|
(*this)[i].allocate(pb, FMT(annotation_prefix, "_%zu", i));
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_variable_array<FieldT>::fill_with_field_elements(protoboard<FieldT> &pb, const std::vector<FieldT>& vals) const
|
|
{
|
|
assert(this->size() == vals.size());
|
|
for (size_t i = 0; i < vals.size(); ++i)
|
|
{
|
|
pb.val((*this)[i]) = vals[i];
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_variable_array<FieldT>::fill_with_bits(protoboard<FieldT> &pb, const bit_vector& bits) const
|
|
{
|
|
assert(this->size() == bits.size());
|
|
for (size_t i = 0; i < bits.size(); ++i)
|
|
{
|
|
pb.val((*this)[i]) = (bits[i] ? FieldT::one() : FieldT::zero());
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_variable_array<FieldT>::fill_with_bits_of_field_element(protoboard<FieldT> &pb, const FieldT &r) const
|
|
{
|
|
const bigint<FieldT::num_limbs> rint = r.as_bigint();
|
|
for (size_t i = 0; i < this->size(); ++i)
|
|
{
|
|
pb.val((*this)[i]) = rint.test_bit(i) ? FieldT::one() : FieldT::zero();
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_variable_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const
|
|
{
|
|
this->fill_with_bits_of_field_element(pb, FieldT(i, true));
|
|
}
|
|
|
|
template<typename FieldT>
|
|
std::vector<FieldT> pb_variable_array<FieldT>::get_vals(const protoboard<FieldT> &pb) const
|
|
{
|
|
std::vector<FieldT> result(this->size());
|
|
for (size_t i = 0; i < this->size(); ++i)
|
|
{
|
|
result[i] = pb.val((*this)[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
bit_vector pb_variable_array<FieldT>::get_bits(const protoboard<FieldT> &pb) const
|
|
{
|
|
bit_vector result;
|
|
for (size_t i = 0; i < this->size(); ++i)
|
|
{
|
|
const FieldT v = pb.val((*this)[i]);
|
|
assert(v == FieldT::zero() || v == FieldT::one());
|
|
result.push_back(v == FieldT::one());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
FieldT pb_variable_array<FieldT>::get_field_element_from_bits(const protoboard<FieldT> &pb) const
|
|
{
|
|
FieldT result = FieldT::zero();
|
|
|
|
for (size_t i = 0; i < this->size(); ++i)
|
|
{
|
|
/* push in the new bit */
|
|
const FieldT v = pb.val((*this)[this->size()-1-i]);
|
|
assert(v == FieldT::zero() || v == FieldT::one());
|
|
result += result + v;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
pb_linear_combination<FieldT>::pb_linear_combination()
|
|
{
|
|
this->is_variable = false;
|
|
this->index = 0;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
pb_linear_combination<FieldT>::pb_linear_combination(const pb_variable<FieldT> &var)
|
|
{
|
|
this->is_variable = true;
|
|
this->index = var.index;
|
|
this->terms.emplace_back(linear_term<FieldT>(var));
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_linear_combination<FieldT>::assign(protoboard<FieldT> &pb, const linear_combination<FieldT> &lc)
|
|
{
|
|
assert(this->is_variable == false);
|
|
this->index = pb.allocate_lc_index();
|
|
this->terms = lc.terms;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_linear_combination<FieldT>::evaluate(protoboard<FieldT> &pb) const
|
|
{
|
|
if (this->is_variable)
|
|
{
|
|
return; // do nothing
|
|
}
|
|
|
|
FieldT sum = 0;
|
|
for (auto term : this->terms)
|
|
{
|
|
sum += term.coeff * pb.val(pb_variable<FieldT>(term.index));
|
|
}
|
|
|
|
pb.lc_val(*this) = sum;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
bool pb_linear_combination<FieldT>::is_constant() const
|
|
{
|
|
if (is_variable)
|
|
{
|
|
return (index == 0);
|
|
}
|
|
else
|
|
{
|
|
for (auto term : this->terms)
|
|
{
|
|
if (term.index != 0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
FieldT pb_linear_combination<FieldT>::constant_term() const
|
|
{
|
|
if (is_variable)
|
|
{
|
|
return (index == 0 ? FieldT::one() : FieldT::zero());
|
|
}
|
|
else
|
|
{
|
|
FieldT result = FieldT::zero();
|
|
for (auto term : this->terms)
|
|
{
|
|
if (term.index == 0)
|
|
{
|
|
result += term.coeff;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_linear_combination_array<FieldT>::evaluate(protoboard<FieldT> &pb) const
|
|
{
|
|
for (size_t i = 0; i < this->size(); ++i)
|
|
{
|
|
(*this)[i].evaluate(pb);
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_linear_combination_array<FieldT>::fill_with_field_elements(protoboard<FieldT> &pb, const std::vector<FieldT>& vals) const
|
|
{
|
|
assert(this->size() == vals.size());
|
|
for (size_t i = 0; i < vals.size(); ++i)
|
|
{
|
|
pb.lc_val((*this)[i]) = vals[i];
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_linear_combination_array<FieldT>::fill_with_bits(protoboard<FieldT> &pb, const bit_vector& bits) const
|
|
{
|
|
assert(this->size() == bits.size());
|
|
for (size_t i = 0; i < bits.size(); ++i)
|
|
{
|
|
pb.lc_val((*this)[i]) = (bits[i] ? FieldT::one() : FieldT::zero());
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_linear_combination_array<FieldT>::fill_with_bits_of_field_element(protoboard<FieldT> &pb, const FieldT &r) const
|
|
{
|
|
const bigint<FieldT::num_limbs> rint = r.as_bigint();
|
|
for (size_t i = 0; i < this->size(); ++i)
|
|
{
|
|
pb.lc_val((*this)[i]) = rint.test_bit(i) ? FieldT::one() : FieldT::zero();
|
|
}
|
|
}
|
|
|
|
template<typename FieldT>
|
|
void pb_linear_combination_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const
|
|
{
|
|
this->fill_with_bits_of_field_element(pb, FieldT(i));
|
|
}
|
|
|
|
template<typename FieldT>
|
|
std::vector<FieldT> pb_linear_combination_array<FieldT>::get_vals(const protoboard<FieldT> &pb) const
|
|
{
|
|
std::vector<FieldT> result(this->size());
|
|
for (size_t i = 0; i < this->size(); ++i)
|
|
{
|
|
result[i] = pb.lc_val((*this)[i]);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
bit_vector pb_linear_combination_array<FieldT>::get_bits(const protoboard<FieldT> &pb) const
|
|
{
|
|
bit_vector result;
|
|
for (size_t i = 0; i < this->size(); ++i)
|
|
{
|
|
const FieldT v = pb.lc_val((*this)[i]);
|
|
assert(v == FieldT::zero() || v == FieldT::one());
|
|
result.push_back(v == FieldT::one());
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
FieldT pb_linear_combination_array<FieldT>::get_field_element_from_bits(const protoboard<FieldT> &pb) const
|
|
{
|
|
FieldT result = FieldT::zero();
|
|
|
|
for (size_t i = 0; i < this->size(); ++i)
|
|
{
|
|
/* push in the new bit */
|
|
const FieldT v = pb.lc_val((*this)[this->size()-1-i]);
|
|
assert(v == FieldT::zero() || v == FieldT::one());
|
|
result += result + v;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
linear_combination<FieldT> pb_sum(const pb_linear_combination_array<FieldT> &v)
|
|
{
|
|
linear_combination<FieldT> result;
|
|
for (auto &term : v)
|
|
{
|
|
result = result + term;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
template<typename FieldT>
|
|
linear_combination<FieldT> pb_packing_sum(const pb_linear_combination_array<FieldT> &v)
|
|
{
|
|
FieldT twoi = FieldT::one(); // will hold 2^i entering each iteration
|
|
std::vector<linear_term<FieldT> > all_terms;
|
|
for (auto &lc : v)
|
|
{
|
|
for (auto &term : lc.terms)
|
|
{
|
|
all_terms.emplace_back(twoi * term);
|
|
}
|
|
twoi += twoi;
|
|
}
|
|
|
|
return linear_combination<FieldT>(all_terms);
|
|
}
|
|
|
|
template<typename FieldT>
|
|
linear_combination<FieldT> pb_coeff_sum(const pb_linear_combination_array<FieldT> &v, const std::vector<FieldT> &coeffs)
|
|
{
|
|
assert(v.size() == coeffs.size());
|
|
std::vector<linear_term<FieldT> > all_terms;
|
|
|
|
auto coeff_it = coeffs.begin();
|
|
for (auto &lc : v)
|
|
{
|
|
for (auto &term : lc.terms)
|
|
{
|
|
all_terms.emplace_back((*coeff_it) * term);
|
|
}
|
|
++coeff_it;
|
|
}
|
|
|
|
return linear_combination<FieldT>(all_terms);
|
|
}
|
|
|
|
|
|
} // libsnark
|
|
#endif // PB_VARIABLE_TCC
|
|
|