diff --git a/bindings/java/java_code/src/main/java/verkle/cryptography/LibIpaMultipoint.java b/bindings/java/java_code/src/main/java/verkle/cryptography/LibIpaMultipoint.java index 547f1ae..63eb607 100644 --- a/bindings/java/java_code/src/main/java/verkle/cryptography/LibIpaMultipoint.java +++ b/bindings/java/java_code/src/main/java/verkle/cryptography/LibIpaMultipoint.java @@ -49,6 +49,15 @@ public class LibIpaMultipoint { * @return uncompressed serialised commitment. */ public static native byte[] commit(byte[] values); + + /** + * Adds two commitments together. + * + * @param lhs first commitment to add in uncompressed format. + * @param rhs second commitment to add in uncompressed format. + * @return sum of lhs and rhs returned in uncompressed format. + */ + public static native byte[] addCommitment(byte[] lhs, byte[] rhs); /** * Commit to a vector of values and compress commitment. diff --git a/bindings/java/java_code/src/test/java/verkle/cryptography/LibIpaMultipointTest.java b/bindings/java/java_code/src/test/java/verkle/cryptography/LibIpaMultipointTest.java index aa43d95..b49e9d8 100644 --- a/bindings/java/java_code/src/test/java/verkle/cryptography/LibIpaMultipointTest.java +++ b/bindings/java/java_code/src/test/java/verkle/cryptography/LibIpaMultipointTest.java @@ -95,7 +95,8 @@ public void testUpdateCommitmentSparseIdentityCommitment() { @Test public void testUpdateCommitmentSparseNonIdentityCommitment() { // These values are taken from: https://github.com/crate-crypto/rust-verkle/blob/bb5af2f2fe9788d49d2896b9614a3125f8227818/ffi_interface/src/lib.rs#L494 - Bytes oldCommitment = Bytes.fromHexString("c2a169fe13aab966d6642801727c8534e40b355372890e18a9880f66b88e143a37fe18000aaf81d4536b64ec3266678c56baf81645d4cfd5133a908247ab8445"); + Bytes oldCommitment = Bytes.fromHexString( + "c2a169fe13aab966d6642801727c8534e40b355372890e18a9880f66b88e143a37fe18000aaf81d4536b64ec3266678c56baf81645d4cfd5133a908247ab8445"); Bytes oldScalar1 = Bytes.fromHexString("0x0400000000000000000000000000000000000000000000000000000000000000"); Bytes newScalar1 = Bytes.fromHexString("0x7f00000000000000000000000000000000000000000000000000000000000000"); Bytes index1 = Bytes.fromHexString("0x01"); @@ -104,15 +105,29 @@ public void testUpdateCommitmentSparseNonIdentityCommitment() { Bytes newScalar2 = Bytes.fromHexString("0xff00000000000000000000000000000000000000000000000000000000000000"); Bytes index2 = Bytes.fromHexString("0x02"); - Bytes indices = Bytes.concatenate(index1, index2); + Bytes indices = Bytes.concatenate(index1, index2); Bytes oldScalars = Bytes.concatenate(oldScalar1, oldScalar2); - Bytes newScalars = Bytes.concatenate(newScalar1, newScalar2); + Bytes newScalars = Bytes.concatenate(newScalar1, newScalar2); Bytes result = Bytes.of(LibIpaMultipoint.updateSparse( - oldCommitment.toArray(), indices.toArray(), - oldScalars.toArray(), newScalars.toArray() - )); - assertThat(result).isEqualTo(Bytes.fromHexString("2dd3bb69da79ecd91a74b188bfddc74827a995dec07e5308f8215f08d69e77330b11628c6d3313a7781b74850e64cb6ac706290da79e56ff311a10214d14dc36")); + oldCommitment.toArray(), indices.toArray(), + oldScalars.toArray(), newScalars.toArray())); + assertThat(result).isEqualTo(Bytes.fromHexString( + "2dd3bb69da79ecd91a74b188bfddc74827a995dec07e5308f8215f08d69e77330b11628c6d3313a7781b74850e64cb6ac706290da79e56ff311a10214d14dc36")); } + + @Test + public void testAddCommitment() { + // Taken from `smoke_test_add_commitment_fixed` in ffi_interface + + Bytes lhs = Bytes.fromHexString("0x0ff070a99e9f38e4f1ec1db91795ef4942fcd188152562c2773d9125236a50444687ab68507977d6276428d7d570a3c95efa406427f6641ba1e247133d17e030"); + Bytes rhs = Bytes.fromHexString("0x333e05d05e6533e993f519c23dbce6205fb9e0b78f38b3336d9c4296f144cb0204c389bb5e6925157ce16eda2ebf45640956be98e2be2df77a86f0bca135da21"); + Bytes expected = Bytes.fromHexString( + "0x8b5feb2eb0cc73a8ca2f24ae7b2c61e88ff0b019dea9b881d1b5f7815280b6393834cb80ab2c09984c5b9f70be680206a6e12c8bbb169fe5ab672f45c5d51e20"); + + Bytes result = Bytes.of(LibIpaMultipoint.addCommitment(lhs.toArray(), rhs.toArray())); + + assertThat(result).isEqualTo(expected); + } } diff --git a/bindings/java/rust_code/Cargo.toml b/bindings/java/rust_code/Cargo.toml index 110a894..48384b0 100644 --- a/bindings/java/rust_code/Cargo.toml +++ b/bindings/java/rust_code/Cargo.toml @@ -9,10 +9,12 @@ repository = { workspace = true } [dependencies] -ffi_interface = { git = "https://github.com/crate-crypto/rust-verkle", rev = "442174edeb69f7827047132306d302345df12b83" } -verkle-trie = { git = "https://github.com/crate-crypto/rust-verkle", rev = "442174edeb69f7827047132306d302345df12b83" } -ipa-multipoint = { git = "https://github.com/crate-crypto/rust-verkle", rev = "442174edeb69f7827047132306d302345df12b83" } -banderwagon = { git = "https://github.com/crate-crypto/rust-verkle", rev = "442174edeb69f7827047132306d302345df12b83" } +banderwagon = { path = "../../../banderwagon" } +ipa-multipoint = { path = "../../../ipa-multipoint" } +verkle-spec = { path = "../../../verkle-spec" } +verkle-trie = { path = "../../../verkle-trie" } +ffi_interface = { path = "../../../ffi_interface" } + jni = { version = "0.21.1", features = [ "invocation", ] } # We use invocation in tests. diff --git a/bindings/java/rust_code/src/lib.rs b/bindings/java/rust_code/src/lib.rs index 6b54a0f..6efd5d2 100644 --- a/bindings/java/rust_code/src/lib.rs +++ b/bindings/java/rust_code/src/lib.rs @@ -278,6 +278,48 @@ pub extern "system" fn Java_verkle_cryptography_LibIpaMultipoint_hash<'local>( result } +#[no_mangle] +pub extern "system" fn Java_verkle_cryptography_LibIpaMultipoint_addCommitment<'local>( + mut env: JNIEnv<'local>, + _class: JClass<'_>, + lhs: JByteArray, + rhs: JByteArray, +) -> JByteArray<'local> { + let lhs = match parse_commitment(&env, lhs) { + Ok(v) => v, + Err(e) => { + env.throw_new("java/lang/IllegalArgumentException", e) + .expect("Failed to throw exception for add commitment."); + return JByteArray::default(); + } + }; + + let rhs = match parse_commitment(&env, rhs) { + Ok(v) => v, + Err(e) => { + env.throw_new("java/lang/IllegalArgumentException", e) + .expect("Failed to throw exception for add commitment."); + return JByteArray::default(); + } + }; + + let output = ffi_interface::add_commitment(lhs, rhs); + + let result = match env.byte_array_from_slice(&output) { + Ok(s) => s, + Err(_e) => { + env.throw_new( + "java/lang/IllegalArgumentException", + "Invalid commitment output. Couldn't convert to byte array.", + ) + .expect("Couldn't convert to byte array"); + return JByteArray::default(); + } + }; + + result +} + #[no_mangle] pub extern "system" fn Java_verkle_cryptography_LibIpaMultipoint_hashMany<'local>( mut env: JNIEnv<'local>, diff --git a/bindings/java/rust_code/verkle_cryptography_LibIpaMultipoint.h b/bindings/java/rust_code/verkle_cryptography_LibIpaMultipoint.h index a83d3f8..17aa80e 100644 --- a/bindings/java/rust_code/verkle_cryptography_LibIpaMultipoint.h +++ b/bindings/java/rust_code/verkle_cryptography_LibIpaMultipoint.h @@ -15,6 +15,14 @@ extern "C" { JNIEXPORT jbyteArray JNICALL Java_verkle_cryptography_LibIpaMultipoint_commit (JNIEnv *, jclass, jbyteArray); +/* + * Class: verkle_cryptography_LibIpaMultipoint + * Method: addCommitment + * Signature: ([B[B)[B + */ +JNIEXPORT jbyteArray JNICALL Java_verkle_cryptography_LibIpaMultipoint_addCommitment + (JNIEnv *, jclass, jbyteArray, jbyteArray); + /* * Class: verkle_cryptography_LibIpaMultipoint * Method: commitAsCompressed diff --git a/ffi_interface/src/lib.rs b/ffi_interface/src/lib.rs index 4402c3c..f974864 100644 --- a/ffi_interface/src/lib.rs +++ b/ffi_interface/src/lib.rs @@ -602,6 +602,22 @@ mod pedersen_hash_tests { assert_eq!(hex::encode(&key), expected_hash) } + #[test] + fn smoke_test_add_commitment_fixed() { + // A test to check that add commitment does not change + let lhs = "0ff070a99e9f38e4f1ec1db91795ef4942fcd188152562c2773d9125236a50444687ab68507977d6276428d7d570a3c95efa406427f6641ba1e247133d17e030"; + let rhs = "333e05d05e6533e993f519c23dbce6205fb9e0b78f38b3336d9c4296f144cb0204c389bb5e6925157ce16eda2ebf45640956be98e2be2df77a86f0bca135da21"; + let output = "8b5feb2eb0cc73a8ca2f24ae7b2c61e88ff0b019dea9b881d1b5f7815280b6393834cb80ab2c09984c5b9f70be680206a6e12c8bbb169fe5ab672f45c5d51e20"; + + let lhs_bytes = hex::decode(lhs).unwrap(); + let rhs_bytes = hex::decode(rhs).unwrap(); + let output_bytes = hex::decode(output).unwrap(); + + let got = add_commitment(lhs_bytes.try_into().unwrap(), rhs_bytes.try_into().unwrap()); + + assert_eq!(&got, &output_bytes[..]) + } + fn u128_to_32bytes(integer: u128) -> [u8; 32] { let mut bytes = integer.to_le_bytes().to_vec(); bytes.extend(vec![0u8; 16]);