diff --git a/.gitignore b/.gitignore index 370b496..b14ab6b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ inc/blst.h* inc/blst_aux.h* .vscode/ +.idea/ .clang-format *bindings/*/*.so *bindings/csharp/*.exe diff --git a/bindings/java/.gitignore b/bindings/java/.gitignore new file mode 100644 index 0000000..3fe20be --- /dev/null +++ b/bindings/java/.gitignore @@ -0,0 +1 @@ +generated/ \ No newline at end of file diff --git a/bindings/java/Makefile b/bindings/java/Makefile new file mode 100644 index 0000000..03c3be7 --- /dev/null +++ b/bindings/java/Makefile @@ -0,0 +1,2 @@ +ckzg4844: + swig -c++ -java -outdir generated/ -I../../src c_kzg_4844.swg \ No newline at end of file diff --git a/bindings/java/README.md b/bindings/java/README.md new file mode 100644 index 0000000..97e4781 --- /dev/null +++ b/bindings/java/README.md @@ -0,0 +1 @@ +## Build Instructions \ No newline at end of file diff --git a/bindings/java/bls12_381.hpp b/bindings/java/bls12_381.hpp new file mode 100644 index 0000000..6153b1f --- /dev/null +++ b/bindings/java/bls12_381.hpp @@ -0,0 +1,93 @@ +#ifndef ___BLS12_381_HPP___ +#define ___BLS12_381_HPP___ + +#include + +#include "../../src/c_kzg_4844.h" +#include "exception.hpp" + +class Fr +{ +private: + fr_t fr; + + Fr(fr_t _fr) { fr = _fr; } + + Fr(int64_t arr[4]) + { + blst_fr_from_uint64(&fr, (const uint64_t *)arr); + } + +public: + static Fr from_jlongs(int64_t arr[4]) + { + return Fr(arr); + } + + Fr() {} + + std::vector to_longs() + { + std::vector ret(4); + blst_uint64_from_fr((uint64_t *)&ret[0], &fr); + return ret; + } +}; + +class G1 +{ +private: + g1_t g1; + + G1(g1_t g1_) { g1 = g1_; } + + G1(uint8_t arr[48]) + throw(KZGException) + { + bytes_to_g1(&g1, arr); + } + +public: + static G1 from_compressed(uint8_t arr[48]) throw(KZGException) + { + return G1(arr); + } + + G1() {} + + void to_compressed(uint8_t out[48]) + { + bytes_from_g1(out, &g1); + } +}; + +class G2 +{ +private: + g2_t g2; + + G2() {} + G2(g2_t g2_) { g2 = g2_; } + G2(const byte arr[96]) + throw(KZGException) + { + blst_p2_affine p2_aff; + BLST_TRY(blst_p2_uncompress(&p2_aff, arr)); + blst_p2_from_affine(&g2, &p2_aff); + } + +public: + static G2 from_compressed(const signed char arr[96]) throw(KZGException) + { + return new G2((byte *)arr); + } + + G2() {} + + void to_compressed(signed char out[96]) + { + blst_p2_compress((byte *)out, &g2); + } +}; + +#endif diff --git a/bindings/java/c_kzg_4844.hpp b/bindings/java/c_kzg_4844.hpp new file mode 100644 index 0000000..7b0bacd --- /dev/null +++ b/bindings/java/c_kzg_4844.hpp @@ -0,0 +1,28 @@ +#ifndef ___C_KZG_4844_HPP___ +#define ___C_KZG_4844_HPP___ + +#include + +#include "c_kzg_4844.h" +#include "bls12_381.hpp" +#include "setup.hpp" +#include "exception.hpp" + +KZGSetup load_trusted_setup_wrap(const char *file) +{ + KZGSettings *out = malloc(sizeof(KZGSettings)); + + FILE *f = fopen(file, "r"); + + CKZG_TRY(load_trusted_setup(out, f)); + + return KZGSetup(); +} + +void free_trusted_setup_wrap(KZGSetup *s) +{ + KZGSettings s_; + CKZG_TRY(free_trusted_setup(s_)) +} + +#endif \ No newline at end of file diff --git a/bindings/java/c_kzg_4844.swg b/bindings/java/c_kzg_4844.swg new file mode 100644 index 0000000..5045e5f --- /dev/null +++ b/bindings/java/c_kzg_4844.swg @@ -0,0 +1,96 @@ +%module CKzg4844 + +%include "exception.i" +%include "std_string.i" +%include "stdint.i" +%include "enums.swg" +%include "arrays_java.i" +%include "std_vector.i" + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("$module"); + } catch (UnsatisfiedLinkError ex) { + throw new RuntimeException(ex); + } + } +%} + +// copied from blst.swg + +// Extensive sorcery to shift memory management to JVM GC. General idea is +// to use Java long[] as opaque storage for blst data. Methods that return +// new objects allocate suitably sized long[] arrays from JVM heap, +// references to which are then assigned to |swigCPtr| on the Java side. +// And when passed back to JNI, |swigCPtr|s are dereferenced with +// GetLongArrayElements... And no destructors! +%nodefaultdtor; +%typemap(javafinalize) SWIGTYPE "" +%typemap(javadestruct) SWIGTYPE "" + +%typemap(javabody) SWIGTYPE %{ + private transient long[] swigCPtr; + + protected $javaclassname(long[] cPtr) { swigCPtr = cPtr; } + + protected static long[] getCPtr($javaclassname obj) { + return obj != null ? obj.swigCPtr : null; + } + + public $javaclassname dup() { return new $javaclassname(swigCPtr.clone()); } +%} +%ignore dup; +%typemap(javaconstruct) SWIGTYPE { this($imcall); } +%typemap(jni) SWIGTYPE, SWIGTYPE&, SWIGTYPE* "jlongArray" +%typemap(jtype) SWIGTYPE, SWIGTYPE&, SWIGTYPE* "long[]" +%typemap(javaout) SWIGTYPE, SWIGTYPE&, SWIGTYPE* { + return new $javaclassname($jnicall); +} +%typemap(in) SWIGTYPE&, SWIGTYPE* %{ + $1 = ($1_ltype)JCALL(GetLongArrayElements, $input, 0); +%} +%typemap(in) const SWIGTYPE&, const SWIGTYPE* %{ + $1 = $input ? ($1_ltype)JCALL(GetLongArrayElements, $input, 0) : NULL; +%} +%typemap(out) SWIGTYPE&, SWIGTYPE* %{ + if ($1 != $null) { + size_t sz = (sizeof($1_basetype) + sizeof(jlong) - 1)/sizeof(jlong); + $result = JCALL(NewLongArray, sz); + if ($result != $null) + JCALL(SetLongArrayRegion, $result, 0, sz, (const jlong *)$1); + } +%} +%typemap(out) SWIGTYPE { + size_t sz = (sizeof($1_basetype) + sizeof(jlong) - 1)/sizeof(jlong); + $result = JCALL(NewLongArray, sz); + if ($result != $null) + JCALL(SetLongArrayRegion, $result, 0, sz, (const jlong *)&$1); +} +%typemap(newfree) SWIGTYPE* "delete $1;" +%typemap(freearg) SWIGTYPE&, SWIGTYPE* %{ + JCALL(ReleaseLongArrayElements, $input, (jlong *)$1, 0); +%} +%typemap(freearg) const SWIGTYPE&, const SWIGTYPE* %{ + if ($input) JCALL(ReleaseLongArrayElements, $input, (jlong *)$1, JNI_ABORT); +%} +%typemap(freearg) const std::string& "" + +// making the generated java interface prettier and more usable +%template(G1Vector) std::vector; +%template(G2Vector) std::vector; +%template(FrVector) std::vector; +%template(LongVector) std::vector; + +%begin %{ +#include "c_kzg_4844.hpp" +#include "bls12_381.hpp" +#include "setup.hpp" +%} + +// remove the _wrap suffix of the functions +%rename("%(regex:/^(.*)(_wrap)$/\\1/)s", %$isfunction) ""; + +%include "c_kzg_4844.hpp" +%include "bls12_381.hpp" +%include "setup.hpp" \ No newline at end of file diff --git a/bindings/java/exception.hpp b/bindings/java/exception.hpp new file mode 100644 index 0000000..cddaca2 --- /dev/null +++ b/bindings/java/exception.hpp @@ -0,0 +1,51 @@ +#ifndef ___EXCEPTION_HPP___ +#define ___EXCEPTION_HPP___ + +#include + +#include "c_kzg_4844.h" + +char *C_KZG_ERRORS[] = { + "C_KZG_OK", + "C_KZG_BADARGS", + "C_KZG_ERROR", + "C_KZG_MALLOC"}; + +char *BLST_ERRORS[] = { + "BLST_SUCCESS", + "BLST_BAD_ENCODING", + "BLST_POINT_NOT_ON_CURVE", + "BLST_POINT_NOT_IN_GROUP", + "BLST_AGGR_TYPE_MISMATCH", + "BLST_VERIFY_FAIL", + "BLST_PK_IS_INFINITY", + "BLST_BAD_SCALAR"}; + +class KZGException +{ + std::string message; + +public: + KZGException(const std::string &msg) : message(msg) {} + + std::string message() + { + return message; + } +}; + +#define CKZG_TRY(result) \ + { \ + C_KZG_RET ___ret = (result); \ + if (___ret != C_KZG_OK) \ + throw KZGException(std::string("C-KZG error: ") + C_KZG_ERRORS[___ret]); \ + } + +#define BLST_TRY(result) \ + { \ + BLST_ERROR ___ret = (result); \ + if (___ret != BLST_SUCCESS) \ + throw KZGException(std::string("BLST error: ") + BLST_ERRORS[___ret]); \ + } + +#endif diff --git a/bindings/java/setup.hpp b/bindings/java/setup.hpp new file mode 100644 index 0000000..3c5f320 --- /dev/null +++ b/bindings/java/setup.hpp @@ -0,0 +1,82 @@ +#ifndef ___SETUP_HPP___ +#define ___SETUP_HPP___ + +#include + +#include "c_kzg_4844.h" +#include "bls12_381.hpp" + +class FFTSetup +{ +private: + uint64_t max_width; + std::vector expanded_roots_of_unity; + std::vector reverse_roots_of_unity; + std::vector roots_of_unity; + +public: + FFTSetup(uint64_t max_width_, std::vector expanded_roots_of_unity_, std::vector reverse_roots_of_unity_, std::vector roots_of_unity_) + { + max_width = max_width_; + expanded_roots_of_unity = expanded_roots_of_unity_; + reverse_roots_of_unity = reverse_roots_of_unity_; + roots_of_unity = roots_of_unity_; + } + + FFTSetup() {} + + uint64_t max_width() + { + return max_width; + } + + std::vector expanded_roots_of_unity() + { + return expanded_roots_of_unity; + } + + std::vector reverse_roots_of_unity() + { + return reverse_roots_of_unity; + } + + std::vector roots_of_unity() + { + return roots_of_unity; + } +}; + +class KZGSetup +{ +private: + FFTSetup fs; + std::vector g1Values; + std::vector g2Values; + +public: + KZGSetup(FFTSetup fs_, std::vector g1Values_, std::vector g2Values_) + { + fs = fs_; + g1Values = g1Values_; + g2Values = g2Values_; + } + + KZGSetup() {} + + FFTSetup fs() + { + return fs; + } + + std::vector g1Values() + { + return g1Values; + } + + std::vector g2Values() + { + return g2Values; + } +}; + +#endif