using jni instead of swig (still needs work)

This commit is contained in:
Stefan Bratanov 2022-11-23 16:32:25 +00:00
parent 2ad9433a2b
commit 3136083139
12 changed files with 172 additions and 406 deletions

View File

@ -1,2 +1,3 @@
generated/
*.cxx
lib/
*.class
*.o

View File

@ -0,0 +1,47 @@
public class CKzg4844JNI {
public static int BYTES_PER_COMMITMENT = 48;
public static int BYTES_PER_PROOF = 48;
public static int FIELD_ELEMENTS_PER_BLOB = 4096;
public static int BYTES_PER_FIELD_ELEMENT = 32;
public static int BYTES_PER_BLOB = FIELD_ELEMENTS_PER_BLOB * BYTES_PER_FIELD_ELEMENT;
static {
try {
System.loadLibrary("ckzg4844jni");
} catch (UnsatisfiedLinkError ex) {
throw new RuntimeException(ex);
}
}
public static native KZGSettings loadTrustedSetup(String file);
public static native void freeTrustedSetup(KZGSettings settings);
public static native byte[] computeAggregateKzgProof(byte[] blobs, int count, KZGSettings settings);
public static native boolean verifyAggregateKzgProof(byte[] blobs, byte[] commitments, int count,
byte[] proof,
KZGSettings settings);
public static native byte[] blobToKzgCommitment(byte[] commitment, KZGSettings settings);
public static native boolean verifyKzgProof(byte[] commitment, byte[] z, byte[] y, byte[] proof, KZGSettings settings);
public static class KZGSettings {
public FFTSettings fs;
public byte[] g1Values;
public byte[] g2Values;
public int g1ValuesCount;
public int g2ValuesCount;
}
public static class FFTSettings {
public long maxWidth;
public long[] expandedRootsOfUnity;
public long[] reverseRootsOfUnity;
public long[] rootsOfUnity;
}
}

View File

@ -1,2 +0,0 @@
ckzg4844:
swig -c++ -java -outdir generated/ -I../../src c_kzg_4844.swg

View File

@ -1 +1,22 @@
## Build Instructions
# Build Shared Library
## Windows
```bat
gcc -c -I..\..\blst\bindings -I..\..\src\ -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" c_kzg_4844_jni.c -o c_kzg_4844_jni.o
gcc -shared -o lib/ckzg4844jni.dll c_kzg_4844.o c_kzg_4844_jni.o -Wl,--add-stdcall-alias
```
## Linux
```bash
gcc -c -fPIC -I../../blst/bindings -I../../src/ -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux c_kzg_4844_jni.c -o c_kzg_4844_jni.o
gcc -shared -fPIC -o lib/libckzg4844jni.so c_kzg_4844.o c_kzg_4844_jni.o -lc
```
## Mac-OS
```bash
gcc -c -fPIC -I../../blst/bindings -I../../src/ -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin c_kzg_4844_jni.c -o c_kzg_4844_jni.o
gcc -dynamiclib -o lib/libckzg4844jni.dylib c_kzg_4844.o c_kzg_4844_jni.o -lc
```

View File

@ -1,93 +0,0 @@
#ifndef ___BLS12_381_HPP___
#define ___BLS12_381_HPP___
#include <vector>
#include "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<long long> to_longs()
{
std::vector<long long> 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_bytes(uint8_t arr[48]) throw(KZGException)
{
return G1(arr);
}
G1() {}
void to_bytes(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_bytes(const signed char arr[96]) throw(KZGException)
{
return new G2((byte *)arr);
}
G2() {}
void to_bytes(signed char out[96])
{
blst_p2_compress((byte *)out, &g2);
}
};
#endif

View File

@ -1,78 +0,0 @@
#ifndef ___C_KZG_4844_HPP___
#define ___C_KZG_4844_HPP___
#include <vector>
#include "c_kzg_4844.h"
#include "bls12_381.hpp"
#include "setup.hpp"
#include "exception.hpp"
// TODO: make it work
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_))
}
G1 compute_aggregate_kzg_proof_wrap(const Blob blobs[], size_t n, const KZGSetup *s)
{
uint8_t out[48];
KZGProof f;
KZGSettings s_;
CKZG_TRY(compute_aggregate_kzg_proof(&f, blobs, n, s_))
bytes_from_g1(out, &f);
return G1::from_bytes(out)
}
bool verify_aggregate_kzg_proof_wrap(const Blob blobs[],
const G1 expected_kzg_commitments[],
size_t n,
const G1 *kzg_aggregated_proof,
const KZGSetup *s)
{
KZGCommitment expected_kzg_commitments_[];
KZGProof kzg_aggregated_proof_;
KZGSettings s_;
bool out;
CKZG_TRY(verify_aggregate_kzg_proof(&out, blobs, expected_kzg_commitments_, n, kzg_aggregated_proof, s_))
return out;
}
G1 blob_to_kzg_commitment_wrap(const Blob blob, const KZGSetup *s)
{
KZGSettings s_;
uint8_t out[48];
KZGCommitment c;
blob_to_kzg_commitment(&c, blob, s_);
bytes_from_g1(out, &c);
return G1::from_bytes(out)
}
bool verify_kzg_proof_wrap(const G1 *polynomial_kzg,
const uint8_t z[BYTES_PER_FIELD_ELEMENT],
const uint8_t y[BYTES_PER_FIELD_ELEMENT],
const G1 *kzg_proof,
const KZGSetup *s)
{
KZGCommitment commitment;
KZGProof proof;
KZGSettings s_;
bool out;
CKZG_TRY(verify_kzg_proof(&out, &commitment, z, y, &proof, s_))
return out;
}
#endif

View File

@ -1,96 +0,0 @@
%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<G1>;
%template(G2Vector) std::vector<G2>;
%template(FrVector) std::vector<Fr>;
%template(LongVector) std::vector<long long>;
%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"

View File

@ -0,0 +1,37 @@
#include "c_kzg_4844_jni.h"
#include "c_kzg_4844.h"
JNIEXPORT jobject JNICALL Java_CKzg4844JNI_loadTrustedSetup(JNIEnv *env, jclass thisCls, jstring file)
{
return NULL;
}
JNIEXPORT void JNICALL Java_CKzg4844JNI_freeTrustedSetup(JNIEnv *env, jclass thisCls, jobject settings)
{
// NO-OP
}
JNIEXPORT jbyteArray JNICALL Java_CKzg4844JNI_computeAggregateKzgProof(JNIEnv *env, jclass thisCls, jbyteArray blobs, jint count, jobject settings)
{
jbyte *blobs_c = (*env)->GetByteArrayElements(env, blobs, NULL);
jbyteArray proof = (*env)->NewByteArray(env, 48);
g1_t *out;
bytes_to_g1(out, (uint8_t *)blobs_c);
return proof;
}
JNIEXPORT jboolean JNICALL Java_CKzg4844JNI_verifyAggregateKzgProof(JNIEnv *env, jclass thisCls, jbyteArray blobs, jbyteArray commitments, jint count, jbyteArray proof, jobject settings)
{
return false;
}
JNIEXPORT jbyteArray JNICALL Java_CKzg4844JNI_blobToKzgCommitment(JNIEnv *env, jclass thisCls, jbyteArray commitment, jobject settings)
{
jbyteArray ret = (*env)->NewByteArray(env, 48);
return ret;
}
JNIEXPORT jboolean JNICALL Java_CKzg4844JNI_verifyKzgProof(JNIEnv *env, jclass thisCls, jbyteArray commitment, jbyteArray z, jbyteArray y, jbyteArray proof, jobject settings)
{
return false;
}

View File

@ -0,0 +1,61 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class CKzg4844JNI */
#ifndef _Included_CKzg4844JNI
#define _Included_CKzg4844JNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: CKzg4844JNI
* Method: loadTrustedSetup
* Signature: (Ljava/lang/String;)LCKzg4844JNI/KZGSettings;
*/
JNIEXPORT jobject JNICALL Java_CKzg4844JNI_loadTrustedSetup
(JNIEnv *, jclass, jstring);
/*
* Class: CKzg4844JNI
* Method: freeTrustedSetup
* Signature: (LCKzg4844JNI/KZGSettings;)V
*/
JNIEXPORT void JNICALL Java_CKzg4844JNI_freeTrustedSetup
(JNIEnv *, jclass, jobject);
/*
* Class: CKzg4844JNI
* Method: computeAggregateKzgProof
* Signature: ([BILCKzg4844JNI/KZGSettings;)[B
*/
JNIEXPORT jbyteArray JNICALL Java_CKzg4844JNI_computeAggregateKzgProof
(JNIEnv *, jclass, jbyteArray, jint, jobject);
/*
* Class: CKzg4844JNI
* Method: verifyAggregateKzgProof
* Signature: ([B[BI[BLCKzg4844JNI/KZGSettings;)Z
*/
JNIEXPORT jboolean JNICALL Java_CKzg4844JNI_verifyAggregateKzgProof
(JNIEnv *, jclass, jbyteArray, jbyteArray, jint, jbyteArray, jobject);
/*
* Class: CKzg4844JNI
* Method: blobToKzgCommitment
* Signature: ([BLCKzg4844JNI/KZGSettings;)[B
*/
JNIEXPORT jbyteArray JNICALL Java_CKzg4844JNI_blobToKzgCommitment
(JNIEnv *, jclass, jbyteArray, jobject);
/*
* Class: CKzg4844JNI
* Method: verifyKzgProof
* Signature: ([B[B[B[BLCKzg4844JNI/KZGSettings;)Z
*/
JNIEXPORT jboolean JNICALL Java_CKzg4844JNI_verifyKzgProof
(JNIEnv *, jclass, jbyteArray, jbyteArray, jbyteArray, jbyteArray, jobject);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,51 +0,0 @@
#ifndef ___EXCEPTION_HPP___
#define ___EXCEPTION_HPP___
#include <string>
#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

View File

@ -1,82 +0,0 @@
#ifndef ___SETUP_HPP___
#define ___SETUP_HPP___
#include <vector>
#include "c_kzg_4844.h"
#include "bls12_381.hpp"
class FFTSetup
{
private:
uint64_t max_width;
std::vector<Fr> expanded_roots_of_unity;
std::vector<Fr> reverse_roots_of_unity;
std::vector<Fr> roots_of_unity;
public:
FFTSetup(uint64_t max_width_, std::vector<Fr> expanded_roots_of_unity_, std::vector<Fr> reverse_roots_of_unity_, std::vector<Fr> 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<Fr> expanded_roots_of_unity()
{
return expanded_roots_of_unity;
}
std::vector<Fr> reverse_roots_of_unity()
{
return reverse_roots_of_unity;
}
std::vector<Fr> roots_of_unity()
{
return roots_of_unity;
}
};
class KZGSetup
{
private:
FFTSetup fs;
std::vector<G1> g1Values;
std::vector<G2> g2Values;
public:
KZGSetup(FFTSetup fs_, std::vector<G1> g1Values_, std::vector<G2> g2Values_)
{
fs = fs_;
g1Values = g1Values_;
g2Values = g2Values_;
}
KZGSetup() {}
FFTSetup fs()
{
return fs;
}
std::vector<G1> g1Values()
{
return g1Values;
}
std::vector<G2> g2Values()
{
return g2Values;
}
};
#endif

View File

@ -15,6 +15,7 @@ blst:
cp libblst.a ../lib && \
cp bindings/*.h ../inc
# Copy make sure c_kzg_4844.o is built and copy it for the NodeJS bindings
# Copy make sure c_kzg_4844.o is built and copy it for the NodeJS and the Java bindings
lib: c_kzg_4844.o Makefile
cp *.o ../bindings/node.js
cp *.o ../bindings/java