Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
296 changes: 113 additions & 183 deletions gnark/gnark-jni/gnark-eip-196.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion gnark/gnark-jni/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.25

toolchain go1.25.4

require github.com/consensys/gnark-crypto v0.19.1-0.20250919185810-d7ecdb060877
require github.com/consensys/gnark-crypto v0.19.2

require (
github.com/bits-and-blooms/bitset v1.24.0 // indirect
Expand Down
8 changes: 4 additions & 4 deletions gnark/gnark-jni/go.sum
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
github.com/bits-and-blooms/bitset v1.24.0 h1:H4x4TuulnokZKvHLfzVRTHJfFfnHEeSYJizujEZvmAM=
github.com/bits-and-blooms/bitset v1.24.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/consensys/gnark-crypto v0.19.1-0.20250919185810-d7ecdb060877 h1:4xq7C8vx7G5T1FFA+PwCcNrVDLMCAT5qFAsAL9GBs7Y=
github.com/consensys/gnark-crypto v0.19.1-0.20250919185810-d7ecdb060877/go.mod h1:OgCH7cSoJ46c+nOzvQuwOrIE9fawpXMYOQFzj22Vy3E=
github.com/consensys/gnark-crypto v0.19.2 h1:qrEAIXq3T4egxqiliFFoNrepkIWVEeIYwt3UL0fvS80=
github.com/consensys/gnark-crypto v0.19.2/go.mod h1:rT23F0XSZqE0mUA0+pRtnL56IbPxs6gp4CeRsBk4XS0=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/leanovate/gopter v0.2.11 h1:vRjThO1EKPb/1NsDXuDrzldR28RLkBflWYcU9CvzWu4=
github.com/leanovate/gopter v0.2.11/go.mod h1:aK3tzZP/C+p1m3SPRE4SYZFGP7jjkuSI4f7Xvpt0S9c=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,31 @@

public class LibGnarkEIP196 {

public static final int EIP196_PREALLOCATE_FOR_RESULT_BYTES = 128;
public static final int EIP196_PREALLOCATE_FOR_ERROR_BYTES = 256; // includes error string
public static final int EIP196_PREALLOCATE_FOR_RESULT_BYTES = 64;
@SuppressWarnings("WeakerAccess")
public static final byte EIP196_ADD_OPERATION_RAW_VALUE = 1;
public static final byte EIP196_MUL_OPERATION_RAW_VALUE = 2;
public static final byte EIP196_PAIR_OPERATION_RAW_VALUE = 3;

public static final boolean ENABLED;

// Keep in sync with the Go code. We use constant values to avoid passing strings from Java to Go
// errCodeSuccess errorCode = iota
// errCodeMalformedPointEIP196
// errCodeInvalidInputPairingLengthEIP196
// errCodePointNotInFieldEIP196
// errCodePointInSubgroupCheckFailedEIP196
// errCodePointOnCurveCheckFailedEIP196
// errCodePairingCheckErrorEIP196
public static final int EIP196_ERR_CODE_SUCCESS = 0;
public static final int EIP196_ERR_CODE_MALFORMED_POINT = 1;
public static final int EIP196_ERR_CODE_INVALID_INPUT_PAIRING_LENGTH = 2;
public static final int EIP196_ERR_CODE_POINT_NOT_IN_FIELD = 3;
public static final int EIP196_ERR_CODE_POINT_IN_SUBGROUP_CHECK_FAILED = 4;
public static final int EIP196_ERR_CODE_POINT_ON_CURVE_CHECK_FAILED = 5;
public static final int EIP196_ERR_CODE_PAIRING_CHECK_ERROR = 6;


static {
boolean enabled;
try {
Expand All @@ -48,21 +64,20 @@ public static int eip196_perform_operation(
byte op,
byte[] i,
int i_len,
byte[] output,
IntByReference o_len,
byte[] err,
IntByReference err_len) {
byte[] output) {

int ret = -1;
switch(op) {
case EIP196_ADD_OPERATION_RAW_VALUE:
ret = eip196altbn128G1Add(i, output, err, i_len, o_len, err_len);
ret = eip196altbn128G1Add(i, output, i_len);
break;
case EIP196_MUL_OPERATION_RAW_VALUE:
ret = eip196altbn128G1Mul(i, output, err, i_len, o_len, err_len);
ret = eip196altbn128G1Mul(i, output, i_len);
break;
case EIP196_PAIR_OPERATION_RAW_VALUE:
ret = eip196altbn128Pairing(i, output, err, i_len, o_len, err_len);
ret = eip196altbn128Pairing(i, output, i_len);
// Result is already written to output buffer by Go
// ret is only non-zero for actual errors
Comment thread
garyschulte marked this conversation as resolved.
Outdated
break;
default:
throw new RuntimeException("Not Implemented EIP-196 operation " + op);
Expand All @@ -74,18 +89,15 @@ public static int eip196_perform_operation(
public static native int eip196altbn128G1Add(
byte[] input,
byte[] output,
byte[] error,
int inputSize, IntByReference outputSize, IntByReference err_len);
int inputSize);

public static native int eip196altbn128G1Mul(
byte[] input,
byte[] output,
byte[] error,
int inputSize, IntByReference output_len, IntByReference err_len);
int inputSize);

public static native int eip196altbn128Pairing(
byte[] input,
byte[] output,
byte[] error,
int inputSize, IntByReference output_len, IntByReference err_len);
int inputSize);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.hyperledger.besu.nativelib.gnark;

import com.google.common.io.CharStreams;
import com.sun.jna.ptr.IntByReference;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -60,20 +59,15 @@ public void shouldCalculate() {
final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe();

final byte[] output = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES];
final IntByReference outputLength = new IntByReference();
final byte[] error = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_ERROR_BYTES];
final IntByReference errorLength = new IntByReference();

LibGnarkEIP196.eip196_perform_operation(LibGnarkEIP196.EIP196_ADD_OPERATION_RAW_VALUE, input,
input.length, output, outputLength, error, errorLength);
int errorCode = LibGnarkEIP196.eip196_perform_operation(LibGnarkEIP196.EIP196_ADD_OPERATION_RAW_VALUE, input,
input.length, output);
final Bytes expectedComputation =
expectedResult == null ? null : Bytes.fromHexString(expectedResult);
if (errorLength.getValue() > 0) {
if (errorCode != LibGnarkEIP196.EIP196_ERR_CODE_SUCCESS) {
assertThat(notes).isNotEmpty();
assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes);
assertThat(outputLength.getValue()).isZero();
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
final Bytes actualComputation = Bytes.wrap(output, 0, LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES);
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.hyperledger.besu.nativelib.gnark;

import com.google.common.io.CharStreams;
import com.sun.jna.ptr.IntByReference;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -60,19 +59,15 @@ public void shouldCalculate() {
final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe();

final byte[] output = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES];
final IntByReference outputLength = new IntByReference();
final byte[] error = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_ERROR_BYTES];
final IntByReference errorLength = new IntByReference();

LibGnarkEIP196.eip196_perform_operation(LibGnarkEIP196.EIP196_MUL_OPERATION_RAW_VALUE, input,
input.length, output, outputLength, error, errorLength);
int errorCode = LibGnarkEIP196.eip196_perform_operation(LibGnarkEIP196.EIP196_MUL_OPERATION_RAW_VALUE, input,
input.length, output);
final Bytes expectedComputation =
expectedResult == null ? null : Bytes.fromHexString(expectedResult);
if (errorLength.getValue() > 0) {
assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).contains(notes);
assertThat(outputLength.getValue()).isZero();
if (errorCode != LibGnarkEIP196.EIP196_ERR_CODE_SUCCESS) {
assertThat(notes).isNotEmpty();
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
final Bytes actualComputation = Bytes.wrap(output, 0, LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES);
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import static org.assertj.core.api.Assertions.assertThat;

import com.sun.jna.ptr.IntByReference;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Ignore;
import org.junit.Test;
Expand Down Expand Up @@ -61,21 +60,15 @@ public void compute_validPoints() {

final byte[] input = Bytes.concatenate(g1Point0, g2Point0, g1Point1, g2Point1).toArrayUnsafe();
final byte[] output = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES];
final IntByReference outputLength = new IntByReference();
final byte[] error = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_ERROR_BYTES];
final IntByReference errorLength = new IntByReference();

int ret = LibGnarkEIP196.eip196_perform_operation(
int errorCode = LibGnarkEIP196.eip196_perform_operation(
LibGnarkEIP196.EIP196_PAIR_OPERATION_RAW_VALUE,
input,
input.length,
output,
outputLength,
error,
errorLength);
output);

assertThat(ret).isEqualTo(0);
assertThat(output[outputLength.getValue() - 1]).isEqualTo((byte) 1);
assertThat(errorCode).isEqualTo(LibGnarkEIP196.EIP196_ERR_CODE_SUCCESS);
assertThat(output[31]).isEqualTo((byte) 1);
}

@Test
Expand Down Expand Up @@ -115,24 +108,14 @@ public void compute_invalidPointsOutsideSubgroupG2() {

final byte[] input = Bytes.concatenate(g1Point0, g2Point0, g1Point1, g2Point1).toArrayUnsafe();
final byte[] output = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES];
final IntByReference outputLength = new IntByReference(output.length);
final byte[] error = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_ERROR_BYTES];
final IntByReference errorLength = new IntByReference();

LibGnarkEIP196.eip196_perform_operation(
int errorCode = LibGnarkEIP196.eip196_perform_operation(
LibGnarkEIP196.EIP196_PAIR_OPERATION_RAW_VALUE,
input,
input.length,
output,
outputLength,
error,
errorLength);
output);

// assert there is an error
assertThat(errorLength.getValue()).isNotEqualTo(0);
String errorStr = new String(error, 0, errorLength.getValue());
assertThat(errorStr).isEqualTo("invalid input parameters, point is not in subgroup");
// assert there is no output
assertThat(outputLength.getValue()).isEqualTo(0);
assertThat(errorCode).isEqualTo(LibGnarkEIP196.EIP196_ERR_CODE_POINT_IN_SUBGROUP_CHECK_FAILED);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
package org.hyperledger.besu.nativelib.gnark;

import com.google.common.io.CharStreams;
import com.sun.jna.ptr.IntByReference;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
import org.junit.runner.RunWith;
Expand Down Expand Up @@ -60,26 +59,19 @@ public void shouldCalculate() {
final byte[] input = Bytes.fromHexString(this.input).toArrayUnsafe();

final byte[] output = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_RESULT_BYTES];
final IntByReference outputLength = new IntByReference();
final byte[] error = new byte[LibGnarkEIP196.EIP196_PREALLOCATE_FOR_ERROR_BYTES];
final IntByReference errorLength = new IntByReference();

LibGnarkEIP196.eip196_perform_operation(
int errorCode = LibGnarkEIP196.eip196_perform_operation(
LibGnarkEIP196.EIP196_PAIR_OPERATION_RAW_VALUE,
input,
input.length,
output,
outputLength,
error,
errorLength);
output);

final Bytes expectedComputation =
expectedResult == null ? null : Bytes.fromHexString(expectedResult);
if (errorLength.getValue() > 0) {
assertThat(new String(error, 0, errorLength.getValue(), UTF_8)).isEqualTo(notes);
assertThat(outputLength.getValue()).isZero();
if (errorCode != LibGnarkEIP196.EIP196_ERR_CODE_SUCCESS) {
assertThat(notes).isNotEmpty();
} else {
final Bytes actualComputation = Bytes.wrap(output, 0, outputLength.getValue());
final Bytes actualComputation = Bytes.wrap(output, 0, 32);
assertThat(actualComputation).isEqualTo(expectedComputation);
assertThat(notes).isEmpty();
}
Expand Down
Loading
Loading