[Java binding] Add test vectors for `verifyKzgProof`
This commit is contained in:
parent
1768321fc3
commit
17fe743fa3
|
@ -1,18 +1,21 @@
|
||||||
# Build Shared Library
|
# Java binding
|
||||||
|
|
||||||
## Prerequisites
|
## Build shared library
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
* Follow the instructions in the [README.md](../../README.md) to build blst.
|
* Follow the instructions in the [README.md](../../README.md) to build blst.
|
||||||
* `JAVA_HOME` environment variable is set to a JDK with an `include` folder containing a `jni.h`
|
* `JAVA_HOME` environment variable is set to a JDK with an `include` folder containing a `jni.h`
|
||||||
file.
|
file.
|
||||||
|
|
||||||
## Build
|
### Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make build
|
make build
|
||||||
```
|
```
|
||||||
|
|
||||||
This will install the library in `src/main/resources/ethereum/ckzg4844/lib` with a folder structure
|
This will install the shared library in `src/main/resources/ethereum/ckzg4844/lib` with a folder
|
||||||
|
structure
|
||||||
and name according to the preset selected (mainnet or minimal) and your OS.
|
and name according to the preset selected (mainnet or minimal) and your OS.
|
||||||
|
|
||||||
All variables which could be passed to the `make` command and the defaults can be found in
|
All variables which could be passed to the `make` command and the defaults can be found in
|
||||||
|
@ -27,8 +30,14 @@ make test
|
||||||
## Benchmark
|
## Benchmark
|
||||||
|
|
||||||
JMH is used for benchmarking.
|
JMH is used for benchmarking.
|
||||||
See [CKZG4844JNIBenchmark.java](src/jmh/java/ethereum/ckzg4844/CKZG4844JNIBenchmark.java) for more information.
|
See [CKZG4844JNIBenchmark.java](src/jmh/java/ethereum/ckzg4844/CKZG4844JNIBenchmark.java) for more
|
||||||
|
information.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make benchmark
|
make benchmark
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Library
|
||||||
|
|
||||||
|
The library which uses this binding and publishes a package to a public maven repo
|
||||||
|
is [jc-kzg-4844](https://github.com/ConsenSys/jc-kzg-4844).
|
|
@ -21,6 +21,7 @@ dependencies {
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter-params:${junitVersion}")
|
testImplementation("org.junit.jupiter:junit-jupiter-params:${junitVersion}")
|
||||||
|
|
||||||
testFixturesImplementation("org.apache.tuweni:tuweni-units:2.3.1")
|
testFixturesImplementation("org.apache.tuweni:tuweni-units:2.3.1")
|
||||||
|
testFixturesImplementation("com.fasterxml.jackson.core:jackson-databind:2.14.1")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,24 @@ public class CKZG4844JNIBenchmark {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
public static class VerifyKzgProofState {
|
||||||
|
|
||||||
|
private byte[] commitment;
|
||||||
|
private byte[] z;
|
||||||
|
private byte[] y;
|
||||||
|
private byte[] proof;
|
||||||
|
|
||||||
|
@Setup
|
||||||
|
public void setUp() {
|
||||||
|
final VerifyKzgProofParameters parameters = TestUtils.getVerifyKzgProofTestVectors().get(2);
|
||||||
|
commitment = parameters.getCommitment();
|
||||||
|
z = parameters.getZ();
|
||||||
|
y = parameters.getY();
|
||||||
|
proof = parameters.getProof();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Setup
|
@Setup
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup.txt");
|
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup.txt");
|
||||||
|
@ -90,4 +108,10 @@ public class CKZG4844JNIBenchmark {
|
||||||
state.proof);
|
state.proof);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||||
|
public boolean verifyKzgProof(final VerifyKzgProofState state) {
|
||||||
|
return CKZG4844JNI.verifyKzgProof(state.commitment, state.z, state.y, state.proof);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,7 +8,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import ethereum.ckzg4844.CKZG4844JNI.Preset;
|
import ethereum.ckzg4844.CKZG4844JNI.Preset;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
|
||||||
public class CKZG4844JNITest {
|
public class CKZG4844JNITest {
|
||||||
|
|
||||||
|
@ -64,22 +67,12 @@ public class CKZG4844JNITest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@ParameterizedTest(name = "{index}")
|
||||||
public void verifiesPointEvaluationPrecompile() {
|
@MethodSource("getVerifyKzgProofTestVectors")
|
||||||
|
public void testVerifyKzgProof(final VerifyKzgProofParameters parameters) {
|
||||||
loadTrustedSetup();
|
assertTrue(
|
||||||
|
CKZG4844JNI.verifyKzgProof(parameters.getCommitment(), parameters.getZ(), parameters.getY(),
|
||||||
final byte[] commitment = new byte[CKZG4844JNI.BYTES_PER_COMMITMENT];
|
parameters.getProof()));
|
||||||
commitment[0] = (byte) 0xc0;
|
|
||||||
final byte[] z = new byte[32];
|
|
||||||
final byte[] y = new byte[32];
|
|
||||||
final byte[] proof = new byte[CKZG4844JNI.BYTES_PER_PROOF];
|
|
||||||
proof[0] = (byte) 0xc0;
|
|
||||||
|
|
||||||
assertTrue(CKZG4844JNI.verifyKzgProof(commitment, z, y, proof));
|
|
||||||
|
|
||||||
CKZG4844JNI.freeTrustedSetup();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -119,7 +112,8 @@ public class CKZG4844JNITest {
|
||||||
|
|
||||||
loadTrustedSetup();
|
loadTrustedSetup();
|
||||||
|
|
||||||
final RuntimeException exception = assertThrows(RuntimeException.class, this::loadTrustedSetup);
|
final RuntimeException exception = assertThrows(RuntimeException.class,
|
||||||
|
CKZG4844JNITest::loadTrustedSetup);
|
||||||
|
|
||||||
assertEquals("Trusted Setup is already loaded. Free it before loading a new one.",
|
assertEquals("Trusted Setup is already loaded. Free it before loading a new one.",
|
||||||
exception.getMessage());
|
exception.getMessage());
|
||||||
|
@ -142,11 +136,17 @@ public class CKZG4844JNITest {
|
||||||
assertEquals("Trusted Setup is not loaded.", exception.getMessage());
|
assertEquals("Trusted Setup is not loaded.", exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadTrustedSetup() {
|
private static void loadTrustedSetup() {
|
||||||
if (PRESET.equals(Preset.MINIMAL)) {
|
if (PRESET.equals(Preset.MINIMAL)) {
|
||||||
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup_4.txt");
|
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup_4.txt");
|
||||||
} else {
|
} else {
|
||||||
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup.txt");
|
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup.txt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Stream<VerifyKzgProofParameters> getVerifyKzgProofTestVectors() {
|
||||||
|
loadTrustedSetup();
|
||||||
|
return TestUtils.getVerifyKzgProofTestVectors().stream()
|
||||||
|
.onClose(CKZG4844JNI::freeTrustedSetup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,28 @@
|
||||||
package ethereum.ckzg4844;
|
package ethereum.ckzg4844;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.apache.tuweni.bytes.Bytes;
|
||||||
|
import org.apache.tuweni.bytes.Bytes32;
|
||||||
import org.apache.tuweni.units.bigints.UInt256;
|
import org.apache.tuweni.units.bigints.UInt256;
|
||||||
|
|
||||||
public class TestUtils {
|
public class TestUtils {
|
||||||
|
|
||||||
|
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
private static final Random RANDOM = new Random();
|
private static final Random RANDOM = new Random();
|
||||||
|
|
||||||
public static byte[] flatten(final byte[]... bytes) {
|
public static byte[] flatten(final byte[]... bytes) {
|
||||||
|
@ -21,8 +34,8 @@ public class TestUtils {
|
||||||
|
|
||||||
public static byte[] createRandomBlob() {
|
public static byte[] createRandomBlob() {
|
||||||
final byte[][] blob = IntStream.range(0, CKZG4844JNI.getFieldElementsPerBlob())
|
final byte[][] blob = IntStream.range(0, CKZG4844JNI.getFieldElementsPerBlob())
|
||||||
.mapToObj(__ -> randomBlsFieldElement())
|
.mapToObj(__ -> randomBLSFieldElement())
|
||||||
.map(blsFieldElement -> blsFieldElement.toArray(ByteOrder.LITTLE_ENDIAN))
|
.map(fieldElement -> fieldElement.toArray(ByteOrder.LITTLE_ENDIAN))
|
||||||
.toArray(byte[][]::new);
|
.toArray(byte[][]::new);
|
||||||
return flatten(blob);
|
return flatten(blob);
|
||||||
}
|
}
|
||||||
|
@ -47,12 +60,47 @@ public class TestUtils {
|
||||||
return flatten(commitments);
|
return flatten(commitments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UInt256 randomBlsFieldElement() {
|
/**
|
||||||
|
* Generated using <a
|
||||||
|
* href="https://github.com/crate-crypto/proto-danksharding-fuzzy-test/">proto-danksharding-fuzzy-test</a>
|
||||||
|
*/
|
||||||
|
public static List<VerifyKzgProofParameters> getVerifyKzgProofTestVectors() {
|
||||||
|
final JsonNode jsonNode;
|
||||||
|
try (InputStream testVectors = readResource("test-vectors/public_verify_kzg_proof.json")) {
|
||||||
|
jsonNode = OBJECT_MAPPER.readTree(testVectors);
|
||||||
|
} catch (final IOException ex) {
|
||||||
|
throw new UncheckedIOException(ex);
|
||||||
|
}
|
||||||
|
final ArrayNode testCases = (ArrayNode) jsonNode.get("TestCases");
|
||||||
|
final Stream.Builder<VerifyKzgProofParameters> testVectors = Stream.builder();
|
||||||
|
testVectors.add(VerifyKzgProofParameters.ZERO);
|
||||||
|
IntStream.range(0,
|
||||||
|
jsonNode.get("NumTestCases").asInt())
|
||||||
|
.mapToObj(i -> {
|
||||||
|
final JsonNode testCase = testCases.get(i);
|
||||||
|
final Bytes32 z = Bytes32.fromHexString(testCase.get("InputPoint").asText());
|
||||||
|
final Bytes32 y = Bytes32.fromHexString(testCase.get("ClaimedValue").asText());
|
||||||
|
final Bytes commitment = Bytes.fromHexString(testCase.get("Commitment").asText(),
|
||||||
|
CKZG4844JNI.BYTES_PER_COMMITMENT);
|
||||||
|
final Bytes proof = Bytes.fromHexString(testCase.get("Proof").asText(),
|
||||||
|
CKZG4844JNI.BYTES_PER_PROOF);
|
||||||
|
return new VerifyKzgProofParameters(commitment.toArray(), z.toArray(), y.toArray(),
|
||||||
|
proof.toArray());
|
||||||
|
})
|
||||||
|
.forEach(testVectors::add);
|
||||||
|
return testVectors.build().collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UInt256 randomBLSFieldElement() {
|
||||||
final BigInteger attempt = new BigInteger(CKZG4844JNI.BLS_MODULUS.bitLength(), RANDOM);
|
final BigInteger attempt = new BigInteger(CKZG4844JNI.BLS_MODULUS.bitLength(), RANDOM);
|
||||||
if (attempt.compareTo(CKZG4844JNI.BLS_MODULUS) < 0) {
|
if (attempt.compareTo(CKZG4844JNI.BLS_MODULUS) < 0) {
|
||||||
return UInt256.valueOf(attempt);
|
return UInt256.valueOf(attempt);
|
||||||
}
|
}
|
||||||
return randomBlsFieldElement();
|
return randomBLSFieldElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream readResource(final String resource) {
|
||||||
|
return Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package ethereum.ckzg4844;
|
||||||
|
|
||||||
|
public class VerifyKzgProofParameters {
|
||||||
|
|
||||||
|
public static final VerifyKzgProofParameters ZERO;
|
||||||
|
|
||||||
|
static {
|
||||||
|
final byte[] commitment = new byte[CKZG4844JNI.BYTES_PER_COMMITMENT];
|
||||||
|
commitment[0] = (byte) 0xc0;
|
||||||
|
final byte[] z = new byte[32];
|
||||||
|
final byte[] y = new byte[32];
|
||||||
|
final byte[] proof = new byte[CKZG4844JNI.BYTES_PER_PROOF];
|
||||||
|
proof[0] = (byte) 0xc0;
|
||||||
|
ZERO = new VerifyKzgProofParameters(commitment, z, y, proof);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final byte[] commitment;
|
||||||
|
private final byte[] z;
|
||||||
|
private final byte[] y;
|
||||||
|
private final byte[] proof;
|
||||||
|
|
||||||
|
public VerifyKzgProofParameters(final byte[] commitment, final byte[] z, final byte[] y,
|
||||||
|
final byte[] proof) {
|
||||||
|
this.commitment = commitment;
|
||||||
|
this.z = z;
|
||||||
|
this.y = y;
|
||||||
|
this.proof = proof;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getCommitment() {
|
||||||
|
return commitment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getProof() {
|
||||||
|
return proof;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue