Skip to content

Commit

Permalink
remove custom serialization code. convenience wrappers around new lib…
Browse files Browse the repository at this point in the history
…ff serialization functions.
  • Loading branch information
dtebbs committed Jul 12, 2021
1 parent 795dae2 commit d4976b5
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 226 deletions.
36 changes: 4 additions & 32 deletions libzeth/core/field_element_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,13 @@

namespace libzeth
{

/// WARNING: The following function assumes that the platform is little-endian
/// and that NAILS are NOT used. See Section 8.2 (page 68):
/// https://gmplib.org/gmp-man-6.2.0.pdf
///
/// In other words, we assume that:
/// - GMP_NUMB_BITS = GMP_LIMB_BITS and thus,
/// - GMP_NAIL_BITS = 0
///
/// Under these assumptions, bigints are layed out in memory with low-order
/// bytes first, occupying `FieldT::num_limbs * GMP_LIMB_BITS / 8` bytes. For
/// readability, this function returns the big-endian hex representation
/// (high-order byte first). If `prefix` is true, add the "0x" prefix.
template<typename FieldT>
std::string bigint_to_hex(
const libff::bigint<FieldT::num_limbs> &limbs, bool prefix = false);

/// WARNING: The following function assumes that the platform is little-endian
/// and that NAILS are NOT used. See Section 8.2 (page 68):
/// https://gmplib.org/gmp-man-6.2.0.pdf
///
/// In other words, we assume that:
/// - GMP_NUMB_BITS = GMP_LIMB_BITS and thus,
/// - GMP_NAIL_BITS = 0
///
/// Hex is read as most-significant-character-first (the natural ordering for
/// numbers), as generated by `bigint_to_hex`.
template<typename FieldT>
libff::bigint<FieldT::num_limbs> bigint_from_hex(const std::string &hex);

/// Convert a base/ground field element to a hexadecimal string.
/// Convert a base field element (single component) to a hexadecimal
/// string (without any JSON decoration such as '"').
template<typename FieldT>
std::string base_field_element_to_hex(const FieldT &field_el);

/// Convert an hexadecimal string to a base/ground field element
/// Convert a plain hex string (without any JSON decoration such as '"') to a
/// base field element (single component).
template<typename FieldT>
FieldT base_field_element_from_hex(const std::string &field_str);

Expand Down
170 changes: 15 additions & 155 deletions libzeth/core/field_element_utils.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -8,182 +8,42 @@
#include "libzeth/core/field_element_utils.hpp"
#include "libzeth/core/utils.hpp"

#include <boost/assert.hpp>
#include <assert.h>
#include <iomanip>

/// This file uses types and preprocessor variables defined in the `gmp.h`
/// header:
/// - `mp_size_t`
/// - `GMP_LIMB_BITS`
/// - `GMP_NAIL_BITS`

namespace libzeth
{

namespace internal
{

template<typename FieldT> class field_element_json
{
public:
/// Convert a field element to JSON
static void write(const FieldT &field_el, std::ostream &out_s)
{
// Note that we write components of extension fields
// highest-order-first.
out_s << '[';
size_t i = FieldT::tower_extension_degree - 1;
do {
out_s << field_element_to_json(field_el.coeffs[i]);
if (i > 0) {
out_s << ',';
}
} while (i-- > 0);
out_s << ']';
}

/// Read a field element from JSON
static void read(FieldT &field_el, std::istream &in_s)
{
// Read opening '[' char, then each component (highest-order-first)
// separated by ',' char, then a closing ']' char.

char sep;
in_s >> sep;
if (sep != '[') {
throw std::runtime_error("expected opening bracket");
}

size_t i = FieldT::tower_extension_degree - 1;
do {
field_element_read_json(field_el.coeffs[i], in_s);
if (i > 0) {
in_s >> sep;
if (sep != ',') {
throw std::runtime_error("expected comma separator");
}
}
} while (i-- > 0);

in_s >> sep;
if (sep != ']') {
throw std::runtime_error("expected closing bracket");
}
}
};

/// Implementation of field_element_json for the base-case of Fp_model
/// types.
template<mp_size_t n, const libff::bigint<n> &modulus>
class field_element_json<libff::Fp_model<n, modulus>>
{
public:
using Field = libff::Fp_model<n, modulus>;
static void write(const Field &field_el, std::ostream &out_s)
{
out_s << '"' << base_field_element_to_hex(field_el) << '"';
};
static void read(Field &field_el, std::istream &in_s)
{
char quote;
in_s >> quote;
if (quote != '"') {
throw std::runtime_error("expected json string");
}
std::string bigint_hex;
try {
std::getline(in_s, bigint_hex, '"');
} catch (...) {
throw std::runtime_error("json string not terminated");
}
field_el = base_field_element_from_hex<Field>(bigint_hex);
}
};

// Generic reader and write for fields and field extensions.
template<typename FieldT> class field_element_bytes
{
public:
static void write(const FieldT &field_el, std::ostream &out_s)
{
for (size_t i = 0; i < FieldT::tower_extension_degree; ++i) {
field_element_write_bytes(field_el.coeffs[i], out_s);
}
}
static void read(FieldT &field_el, std::istream &in_s)
{
for (size_t i = 0; i < FieldT::tower_extension_degree; ++i) {
field_element_read_bytes(field_el.coeffs[i], in_s);
}
}
};

/// Implementation of field_element_bytes for the base-case of Fp_model types.
/// Big-endian bigint values (i.e. not in montgomery form).
template<mp_size_t n, const libff::bigint<n> &modulus>
class field_element_bytes<libff::Fp_model<n, modulus>>
{
public:
using Field = libff::Fp_model<n, modulus>;
static void write(const Field &field_el, std::ostream &out_s)
{
// Convert to bigint, reverse bytes in-place, and write to stream.
const libff::bigint<n> bi = field_el.as_bigint();
std::reverse((char *)(&bi), (char *)(&bi + 1));
out_s.write((const char *)(&bi.data[0]), sizeof(bi));
}
static void read(Field &field_el, std::istream &in_s)
{
// Read bigint from stream, reverse bytes in-place and convert to field
// element.
libff::bigint<n> res;
in_s.read((char *)(&res.data[0]), sizeof(res));
std::reverse((char *)(&res), (char *)(&res + 1));
field_el = Field(res);
}
};

} // namespace internal

template<typename FieldT>
std::string bigint_to_hex(
const libff::bigint<FieldT::num_limbs> &limbs, bool prefix)
{
return bytes_to_hex_reversed(&limbs.data[0], sizeof(limbs.data), prefix);
}

template<typename FieldT>
libff::bigint<FieldT::num_limbs> bigint_from_hex(const std::string &hex)
{
libff::bigint<FieldT::num_limbs> res;
hex_to_bytes_reversed(hex, &res.data[0], sizeof(res.data));
return res;
}

template<typename FieldT>
std::string base_field_element_to_hex(const FieldT &field_el)
{
// Serialize a "ground/base" field element
BOOST_ASSERT(FieldT::extension_degree() == 1);
return bigint_to_hex<FieldT>(field_el.as_bigint(), true);
static_assert(
FieldT::extension_degree() == 1, "only valid on base/ground fields");
return libff::bigint_to_hex(field_el.as_bigint(), true);
}

template<typename FieldT>
FieldT base_field_element_from_hex(const std::string &hex)
{
return FieldT(bigint_from_hex<FieldT>(hex));
static_assert(
FieldT::extension_degree() == 1, "only valid on base/ground fields");
using BigIntT =
typename std::decay<decltype(((FieldT *)nullptr)->mont_repr)>::type;
BigIntT v;
libff::bigint_from_hex(v, hex);
return FieldT(v);
}

template<typename FieldT>
void field_element_write_json(const FieldT &el, std::ostream &out_s)
{
internal::field_element_json<FieldT>::write(el, out_s);
libff::field_write<libff::encoding_json, libff::form_plain>(el, out_s);
}

template<typename FieldT>
void field_element_read_json(FieldT &el, std::istream &in_s)
{
internal::field_element_json<FieldT>::read(el, in_s);
libff::field_read<libff::encoding_json, libff::form_plain>(el, in_s);
}

template<typename FieldT> std::string field_element_to_json(const FieldT &el)
Expand All @@ -207,13 +67,13 @@ FieldT field_element_from_json(const std::string &json)
template<typename FieldT>
void field_element_write_bytes(const FieldT &el, std::ostream &out_s)
{
internal::field_element_bytes<FieldT>::write(el, out_s);
libff::field_write<libff::encoding_binary, libff::form_plain>(el, out_s);
}

template<typename FieldT>
void field_element_read_bytes(FieldT &el, std::istream &in_s)
{
internal::field_element_bytes<FieldT>::read(el, in_s);
libff::field_read<libff::encoding_binary, libff::form_plain>(el, in_s);
}

} // namespace libzeth
Expand Down
4 changes: 2 additions & 2 deletions libzeth/serialization/proto_utils.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ template<typename ppT>
void pairing_parameters_to_proto(zeth_proto::PairingParameters &pp_proto)
{
pp_proto.set_name(pp_name<ppT>());
pp_proto.set_r(bigint_to_hex<libff::Fr<ppT>>(libff::Fr<ppT>::mod));
pp_proto.set_q(bigint_to_hex<libff::Fq<ppT>>(libff::Fq<ppT>::mod));
pp_proto.set_r(libff::bigint_to_hex(libff::Fr<ppT>::mod));
pp_proto.set_q(libff::bigint_to_hex(libff::Fq<ppT>::mod));
*pp_proto.mutable_generator_g1() =
point_g1_affine_to_proto<ppT>(libff::G1<ppT>::one());
*pp_proto.mutable_generator_g2() =
Expand Down
6 changes: 2 additions & 4 deletions libzeth/serialization/r1cs_serialization.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ void constraints_write_json(
out_s << "{";
out_s << "\"index\":" << lt.index << ",";
out_s << "\"value\":"
<< "\"" + bigint_to_hex<FieldT>(lt.coeff.as_bigint(), true)
<< "\"";
<< "\"" + base_field_element_to_hex(lt.coeff) << "\"";
out_s << "}";
count++;
}
Expand Down Expand Up @@ -152,8 +151,7 @@ std::ostream &r1cs_write_json(

out_s << "{\n";
out_s << "\"scalar_field_characteristic\":"
<< "\"" + bigint_to_hex<FieldT>(FieldT::field_char(), true)
<< "\",\n";
<< "\"" + libff::bigint_to_hex(FieldT::field_char(), true) << "\",\n";
out_s << "\"num_variables\":" << r1cs.num_variables() << ",\n";
out_s << "\"num_constraints\":" << r1cs.num_constraints() << ",\n";
out_s << "\"num_inputs\": " << r1cs.num_inputs() << ",\n";
Expand Down
6 changes: 2 additions & 4 deletions libzeth/tests/core/ec_operation_data_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ template<typename ppT> void operation_test_data()
std::stringstream binary_stream;

std::cout << " Fr:";
std::cout << "\n r: "
<< bigint_to_hex<libff::Fr<ppT>>(libff::Fr<ppT>::mod);
std::cout << "\n r: " << libff::bigint_to_hex(libff::Fr<ppT>::mod);

std::cout << "\n 1: ";
field_element_write_json(fr_1, std::cout);
Expand All @@ -69,8 +68,7 @@ template<typename ppT> void operation_test_data()
field_element_write_bytes(fr_minus_2, binary_stream);

std::cout << " Fq:";
std::cout << "\n q: "
<< bigint_to_hex<libff::Fq<ppT>>(libff::Fq<ppT>::mod);
std::cout << "\n q: " << libff::bigint_to_hex(libff::Fq<ppT>::mod);

std::cout << "\n G1:";
std::cout << "\n 1: ";
Expand Down
29 changes: 0 additions & 29 deletions libzeth/tests/core/field_element_utils_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,6 @@ template<typename FieldT> libff::bigint<FieldT::num_limbs> dummy_bigint()
return FieldT::random_element().as_bigint();
}

template<typename FieldT> void do_bigint_encode_decode_hex_test()
{
const libff::bigint<FieldT::num_limbs> bi = dummy_bigint<FieldT>();
const std::string bi_hex = libzeth::bigint_to_hex<FieldT>(bi);
const libff::bigint<FieldT::num_limbs> bi_decoded =
libzeth::bigint_from_hex<FieldT>(bi_hex);
std::cout << "bi_hex: " << bi_hex << std::endl;
std::cout << "bi_decoded_hex: "
<< libzeth::bigint_to_hex<FieldT>(bi_decoded) << std::endl;

ASSERT_EQ(2 * sizeof(bi.data), bi_hex.size());
ASSERT_EQ(bi, bi_decoded);
}

template<typename ppT> void bigint_encode_decode_hex_test()
{
do_bigint_encode_decode_hex_test<libff::Fr<ppT>>();
do_bigint_encode_decode_hex_test<libff::Fq<ppT>>();
}

template<typename FieldT> void do_base_field_element_encode_decode_hex_test()
{
const FieldT fe = FieldT::random_element();
Expand Down Expand Up @@ -148,15 +128,6 @@ template<typename ppT> void field_element_read_write_bytes_test()
do_field_element_read_write_bytes_test<libff::Fqk<ppT>>();
}

TEST(FieldElementUtilsTest, BigIntEncodeDecodeHex)
{
bigint_encode_decode_hex_test<libff::alt_bn128_pp>();
bigint_encode_decode_hex_test<libff::mnt4_pp>();
bigint_encode_decode_hex_test<libff::mnt6_pp>();
bigint_encode_decode_hex_test<libff::bls12_377_pp>();
bigint_encode_decode_hex_test<libff::bw6_761_pp>();
}

TEST(FieldElementUtilsTest, BaseFieldElementEncodeDecodeHex)
{
base_field_element_encode_decode_hex_test<libff::alt_bn128_pp>();
Expand Down

0 comments on commit d4976b5

Please sign in to comment.