[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.
|
||||
* `JAVA_HOME` environment variable is set to a JDK with an `include` folder containing a `jni.h`
|
||||
file.
|
||||
|
||||
## Build
|
||||
### Build
|
||||
|
||||
```bash
|
||||
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.
|
||||
|
||||
All variables which could be passed to the `make` command and the defaults can be found in
|
||||
|
@ -27,8 +30,14 @@ make test
|
|||
## Benchmark
|
||||
|
||||
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
|
||||
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}")
|
||||
|
||||
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
|
||||
public void setUp() {
|
||||
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup.txt");
|
||||
|
@ -90,4 +108,10 @@ public class CKZG4844JNIBenchmark {
|
|||
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 java.util.Optional;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
public class CKZG4844JNITest {
|
||||
|
||||
|
@ -64,22 +67,12 @@ public class CKZG4844JNITest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifiesPointEvaluationPrecompile() {
|
||||
|
||||
loadTrustedSetup();
|
||||
|
||||
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;
|
||||
|
||||
assertTrue(CKZG4844JNI.verifyKzgProof(commitment, z, y, proof));
|
||||
|
||||
CKZG4844JNI.freeTrustedSetup();
|
||||
|
||||
@ParameterizedTest(name = "{index}")
|
||||
@MethodSource("getVerifyKzgProofTestVectors")
|
||||
public void testVerifyKzgProof(final VerifyKzgProofParameters parameters) {
|
||||
assertTrue(
|
||||
CKZG4844JNI.verifyKzgProof(parameters.getCommitment(), parameters.getZ(), parameters.getY(),
|
||||
parameters.getProof()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -119,7 +112,8 @@ public class CKZG4844JNITest {
|
|||
|
||||
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.",
|
||||
exception.getMessage());
|
||||
|
@ -142,11 +136,17 @@ public class CKZG4844JNITest {
|
|||
assertEquals("Trusted Setup is not loaded.", exception.getMessage());
|
||||
}
|
||||
|
||||
private void loadTrustedSetup() {
|
||||
private static void loadTrustedSetup() {
|
||||
if (PRESET.equals(Preset.MINIMAL)) {
|
||||
CKZG4844JNI.loadTrustedSetup("../../src/trusted_setup_4.txt");
|
||||
} else {
|
||||
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;
|
||||
|
||||
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.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
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;
|
||||
|
||||
public class TestUtils {
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
|
||||
public static byte[] flatten(final byte[]... bytes) {
|
||||
|
@ -21,8 +34,8 @@ public class TestUtils {
|
|||
|
||||
public static byte[] createRandomBlob() {
|
||||
final byte[][] blob = IntStream.range(0, CKZG4844JNI.getFieldElementsPerBlob())
|
||||
.mapToObj(__ -> randomBlsFieldElement())
|
||||
.map(blsFieldElement -> blsFieldElement.toArray(ByteOrder.LITTLE_ENDIAN))
|
||||
.mapToObj(__ -> randomBLSFieldElement())
|
||||
.map(fieldElement -> fieldElement.toArray(ByteOrder.LITTLE_ENDIAN))
|
||||
.toArray(byte[][]::new);
|
||||
return flatten(blob);
|
||||
}
|
||||
|
@ -47,12 +60,47 @@ public class TestUtils {
|
|||
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);
|
||||
if (attempt.compareTo(CKZG4844JNI.BLS_MODULUS) < 0) {
|
||||
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