From 9b2e7bb82375d0eb5a289973c7982221318d579b Mon Sep 17 00:00:00 2001 From: kevaundray Date: Mon, 29 Jan 2024 14:27:42 +0000 Subject: [PATCH] chore: Switch to `ffi_interface` ipa-multipoint (#139) Signed-off-by: Kevaundray Wedderburn --- .github/workflows/build.yml | 6 +- ipa-multipoint/ipa_multipoint_jni/Cargo.toml | 13 +- ipa-multipoint/ipa_multipoint_jni/src/lib.rs | 191 +++++++------------ 3 files changed, 76 insertions(+), 134 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d351f05..45bbdc2a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: export PATH=$GOROOT/bin:$PATH # rust dependencies export CARGO_HOME="$HOME/.cargo" - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.68.2 + curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.75.0 - name: Checkout Repo uses: actions/checkout@v4 with: @@ -123,7 +123,7 @@ jobs: brew install go@1.20 || true # rust dependencies export CARGO_HOME="$HOME/.cargo" - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.68.2 + curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.75.0 # install both x86 and arm64 toolchains export PATH="$HOME/.cargo/bin:$PATH" rustup target add x86_64-apple-darwin @@ -189,7 +189,7 @@ jobs: brew install go@1.20 || true # rust dependencies export CARGO_HOME="$HOME/.cargo" - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.68.2 + curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.75.0 # install both x86 and arm64 toolchains export PATH="$HOME/.cargo/bin:$PATH" rustup target add x86_64-apple-darwin diff --git a/ipa-multipoint/ipa_multipoint_jni/Cargo.toml b/ipa-multipoint/ipa_multipoint_jni/Cargo.toml index ec539e4b..c99090e8 100644 --- a/ipa-multipoint/ipa_multipoint_jni/Cargo.toml +++ b/ipa-multipoint/ipa_multipoint_jni/Cargo.toml @@ -22,21 +22,14 @@ repository = "https://github.com/hyperledger/besu-native" edition = "2018" [dependencies] -verkle-spec = { git = "https://github.com/crate-crypto/rust-verkle", rev = "67d47d9e78f873da7c9e72687158468041059b5d" } -verkle-trie = { git = "https://github.com/crate-crypto/rust-verkle", rev = "67d47d9e78f873da7c9e72687158468041059b5d" } -ipa-multipoint = { git = "https://github.com/crate-crypto/ipa_multipoint", branch = "banderwagon_migration" } -banderwagon = { git = "https://github.com/crate-crypto/banderwagon" } -bandersnatch = "0.1.1" -ark-ff = { version = "^0.3.0", default-features = false } -ark-ec = { version = "^0.3.0", default-features = false } -ark-serialize = { version = "^0.3.0", default-features = false } -ark-std = { version = "^0.3.0", default-features = false } +ffi_interface = { git = "https://github.com/crate-crypto/rust-verkle", rev = "13dd7e9b4cb4491230fb0bda1759ef9c62938f28" } +ipa-multipoint = { git = "https://github.com/crate-crypto/rust-verkle", rev = "13dd7e9b4cb4491230fb0bda1759ef9c62938f28" } jni = { version = "0.19.0", features = [ "invocation", ] } # We use invocation in tests. hex = "0.4.3" num-bigint = "0.4.4" - +once_cell = "1.19.0" [lib] name = "ipa_multipoint_jni" diff --git a/ipa-multipoint/ipa_multipoint_jni/src/lib.rs b/ipa-multipoint/ipa_multipoint_jni/src/lib.rs index 769104e8..09a9305f 100644 --- a/ipa-multipoint/ipa_multipoint_jni/src/lib.rs +++ b/ipa-multipoint/ipa_multipoint_jni/src/lib.rs @@ -12,23 +12,27 @@ * * SPDX-License-Identifier: Apache-2.0 */ -use ark_ff::PrimeField; -use banderwagon::{Fr, multi_scalar_mul}; -use ipa_multipoint::crs::CRS; -use verkle_spec::*; -// use crate::{vergroup_to_field}; -use ark_serialize::CanonicalSerialize; -use verkle_trie::*; -// use group_to_field; +use std::convert::TryInto; -use jni::JNIEnv; +use ipa_multipoint::committer::DefaultCommitter; +use ipa_multipoint::crs::CRS; use jni::objects::JClass; use jni::sys::jbyteArray; +use jni::JNIEnv; +use once_cell::sync::Lazy; +pub struct Config { + committer: DefaultCommitter, +} -// Copied from rust-verkle: https://github.com/crate-crypto/rust-verkle/blob/581200474327f5d12629ac2e1691eff91f944cec/verkle-trie/src/constants.rs#L12 -const PEDERSEN_SEED: &'static [u8] = b"eth_verkle_oct_2021"; +// TODO: Use a pointer here instead. This is only being used so that the interface does not get changed. +// TODO: and bindings do not need to be modified. +pub static CONFIG: Lazy = Lazy::new(|| { + let crs = CRS::default(); + let committer = DefaultCommitter::new(&crs.G); + Config { committer } +}); /// Pedersen hash receives an address and a trie index and returns a hash calculated this way: /// H(constant || address_low || address_high || trie_index_low || trie_index_high) @@ -45,130 +49,75 @@ pub extern "system" fn Java_org_hyperledger_besu_nativelib_ipamultipoint_LibIpaM _class: JClass, input: jbyteArray, ) -> jbyteArray { - let input = env.convert_byte_array(input).unwrap(); - let mut address32 = [0u8; 32]; - - address32.copy_from_slice(&input[0..32]); - - let mut trie_index= [0u8; 32]; - - trie_index.copy_from_slice(&input[32..64]); - trie_index.reverse(); // reverse for little endian per specs - - let base_hash = hash_addr_int(&address32, &trie_index); - - let result = base_hash.as_fixed_bytes(); - let output = env.byte_array_from_slice(result).unwrap(); - output -} - -// Helper function to hash an address and an integer taken from rust-verkle/verkle-specs. -pub(crate) fn hash_addr_int(addr: &[u8; 32], integer: &[u8; 32]) -> H256 { - - let address_bytes = addr; - - let integer_bytes = integer; - let mut hash_input = [0u8; 64]; - let (first_half, second_half) = hash_input.split_at_mut(32); - - // Copy address and index into slice, then hash it - first_half.copy_from_slice(address_bytes); - second_half.copy_from_slice(integer_bytes); + let committer = &CONFIG.committer; + + let mut input: [u8; 64] = match input.try_into() { + Ok(input) => input, + Err(_) => { + env.throw_new( + "java/lang/IllegalArgumentException", + "Invalid input length. Should be 64-bytes.", + ) + .expect("Failed to throw exception"); + return std::ptr::null_mut(); // Return null pointer to indicate an error + } + }; + + // The tree_index is interpreted as a little endian integer + // But its given in big endian format. + // The tree_index is the last 32 bytes of the input, + // so we use this method to reverse its endian + fn reverse_last_32_bytes(arr: &mut [u8; 64]) { + let last_32 = &mut arr[32..]; + last_32.reverse(); + } + reverse_last_32_bytes(&mut input); - hash64(hash_input) + let hash = ffi_interface::get_tree_key_hash(committer, input); + env.byte_array_from_slice(&hash).unwrap() } /// Commit receives a list of 32 byte scalars and returns a 32 byte scalar /// Scalar is actually the map_to_field(commitment) because we want to reuse the commitment in parent node. /// This is ported from rust-verkle. #[no_mangle] -pub extern "system" fn Java_org_hyperledger_besu_nativelib_ipamultipoint_LibIpaMultipoint_commit(env: JNIEnv, - _class: JClass<'_>, - input: jbyteArray) - -> jbyteArray { - // Input should be a multiple of 32-be-bytes. - let inp = env.convert_byte_array(input).expect("Cannot convert jbyteArray to rust array"); - let len = inp.len(); - if len % 32 != 0 { - env.throw_new("java/lang/IllegalArgumentException", "Invalid input length. Should be a multiple of 32-bytes.") - .expect("Failed to throw exception"); - return std::ptr::null_mut(); // Return null pointer to indicate an error - } - let n_scalars = len / 32; - if n_scalars > 256 { - env.throw_new("java/lang/IllegalArgumentException", "Invalid input length. Should be at most 256 elements of 32-bytes.") - .expect("Failed to throw exception"); - return std::ptr::null_mut(); // Return null pointer to indicate an error - } - - // Each 32-be-bytes are interpreted as field elements. - let mut scalars: Vec = Vec::with_capacity(n_scalars); - for b in inp.chunks(32) { - scalars.push(Fr::from_be_bytes_mod_order(b)); - } - - // Committing all values at once. - let bases = CRS::new(n_scalars, PEDERSEN_SEED); - let commit = multi_scalar_mul(&bases.G, &scalars); - - // Serializing via x/y in projective coordinates, to int and to scalars. - let scalar = group_to_field(&commit); - let mut scalar_bytes = [0u8; 32]; - scalar.serialize(&mut scalar_bytes[..]).expect("could not serialise Fr into a 32 byte array"); - scalar_bytes.reverse(); - - return env.byte_array_from_slice(&scalar_bytes).expect("Couldn't convert to byte array"); -} +pub extern "system" fn Java_org_hyperledger_besu_nativelib_ipamultipoint_LibIpaMultipoint_commit( + env: JNIEnv, + _class: JClass<'_>, + input: jbyteArray, +) -> jbyteArray { + let input = env + .convert_byte_array(input) + .expect("Cannot convert jbyteArray to rust array"); + + let committer = &CONFIG.committer; + + let commitment = ffi_interface::commit_to_scalars(committer, &input).unwrap(); + let hash = ffi_interface::hash_commitment(commitment); + env.byte_array_from_slice(&hash) + .expect("Couldn't convert to byte array") +} /// Commit_root receives a list of 32 byte scalars and returns a 32 byte commitment.to_bytes() /// This is ported from rust-verkle. #[no_mangle] -pub extern "system" fn Java_org_hyperledger_besu_nativelib_ipamultipoint_LibIpaMultipoint_commitRoot(env: JNIEnv, - _class: JClass<'_>, - input: jbyteArray) - -> jbyteArray { - // Input should be a multiple of 32-be-bytes. - let inp = env.convert_byte_array(input).expect("Cannot convert jbyteArray to rust array"); - let len = inp.len(); - if len % 32 != 0 { - env.throw_new("java/lang/IllegalArgumentException", "Invalid input length. Should be a multiple of 32-bytes.") - .expect("Failed to throw exception"); - return std::ptr::null_mut(); // Return null pointer to indicate an error - } - let n_scalars = len / 32; - if n_scalars > 256 { - env.throw_new("java/lang/IllegalArgumentException", "Invalid input length. Should be at most 256 elements of 32-bytes.") - .expect("Failed to throw exception"); - return std::ptr::null_mut(); // Return null pointer to indicate an error - } - - // Each 32-be-bytes are interpreted as field elements. - let mut scalars: Vec = Vec::with_capacity(n_scalars); - for b in inp.chunks(32) { - scalars.push(Fr::from_be_bytes_mod_order(b)); - } - - // Committing all values at once. - let bases = CRS::new(n_scalars, PEDERSEN_SEED); - let commit = multi_scalar_mul(&bases.G, &scalars); - - // Serializing using first affine coordinate - let commit_bytes = commit.to_bytes(); +pub extern "system" fn Java_org_hyperledger_besu_nativelib_ipamultipoint_LibIpaMultipoint_commitRoot( + env: JNIEnv, + _class: JClass<'_>, + input: jbyteArray, +) -> jbyteArray { + let input = env + .convert_byte_array(input) + .expect("Cannot convert jbyteArray to rust array"); - return env.byte_array_from_slice(&commit_bytes).expect("Couldn't convert to byte array"); -} + let committer = &CONFIG.committer; + let commitment = ffi_interface::commit_to_scalars(committer, &input).unwrap(); + let hash = ffi_interface::deprecated_serialize_commitment(commitment); -// Note: This is a 2 to 1 map, but the two preimages are identified to be the same -// TODO: Create a document showing that this poses no problems -pub(crate)fn group_to_field(point: &Element) -> Fr { - let base_field = point.map_to_field(); - let mut bytes = [0u8; 32]; - base_field - .serialize(&mut bytes[..]) - .expect("could not serialise point into a 32 byte array"); - Fr::from_le_bytes_mod_order(&bytes) -} \ No newline at end of file + env.byte_array_from_slice(&hash) + .expect("Couldn't convert to byte array") +}