Open defuse opened 9 years ago
Note, this blog post describes the same kind of issue and introduces a new C++0x language extension to address the issue:
Perhaps libsnark should use that mechanism?
Ugh, how many hacky workarounds is C++ going to add in the language to address broken linker technology? :-/
In libsnark each Fp_model<num_limbs, modulus>
is used in conjunction with particular elliptic curve choices. Given this the following should work:
fp.hpp
mark each static data member of Fp_model
as extern. For example,template<mp_size_t n, const bigint<n>& modulus>
extern size_t Fp_model<n, modulus>::num_bits
This would ensure that translation units for your executable won't declare their own copy of those symbols.
Fp_model
declare the static data members inside the CURVE_init.cpp
. E.g. inside curves/bn128/bn128_init.cpp
, we would have size_t Fp_model<bn128_r_limbs, bn128_modulus_r>::num_bits
.Of course, The amount of boilerplate can be reduced by an appropriate DECLARE_FP_MODEL_STATIC_MEMBERS(num_limbs, modulus)
macro.
We rely on extern template
anyway, so maybe solution based on that would be a better choice.
By the way, I was unable to exhibit the behavior you observe on my machine: all static members of template instantiations get "weak" bindings in libsnark.so
so the dynamic linker should just DTRT. But that might just be an artifact of my setup (g++ 5.2.1 on Ubuntu wily).
In
algebra/fields/fp.hpp
, the static members of theFp_model
template are declared as well as defined. This leads to a problem when we dynamically link againstlibsnark.so
. We have code in the main executable which tries to access those static members, but when that code runs, it finds them all uninitialized, even though we've run the initialization method.By
#include
-ingalgebra/fields/fp.hpp
in our code, the compiler seems to be creating another copy of all of the static members in our binary. Code in our binary therefore accesses its local copies, which are in the uninitialized state, i.e.num_bits
is zero, because theinit_alt_bn128_params()
initializes the copy of the variable inlibsnark.so
, and not the copy in our binary.Ideally, there should only be one copy of these variables in
libsnark.so
. Is there a trick to getting our code to use the ones insidelibsnark.so
instead of creating copies?We are using
gcc version 5.2.0
.The revision we are using is:
Could this have been fixed in a newer version?