From 107b97390ff84e86490ec66ee820261738954b99 Mon Sep 17 00:00:00 2001 From: "Ya-wen, Jeng" Date: Thu, 7 Dec 2023 03:23:06 -0600 Subject: [PATCH] test(ffi): add `.kts` tests (#47) --- .github/workflows/build-and-test.yml | 5 +- mopro-ffi/Cargo.toml | 6 +- mopro-ffi/README.md | 10 + .../tests/bindings/test_mopro_keccak2.kts | 253 ++++++++++++++++++ .../tests/bindings/test_mopro_keccak2.swift | 68 ++--- mopro-ffi/tests/test_generated_bindings.rs | 1 + 6 files changed, 305 insertions(+), 38 deletions(-) create mode 100644 mopro-ffi/tests/bindings/test_mopro_keccak2.kts diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 063b4619..85903a5d 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -26,7 +26,10 @@ jobs: - name: Run core tests run: cd mopro-core && cargo test -- --nocapture - name: Run ffi tests - run: cd mopro-ffi/ && cargo test -- --nocapture + run: | + cd mopro-ffi/ + curl -L https://repo1.maven.org/maven2/net/java/dev/jna/jna/5.13.0/jna-5.13.0.jar -o target/jna-5.13.0.jar + CLASSPATH=target/jna-5.13.0.jar cargo test -- --nocapture - name: Run ios tests run: | cd mopro-ios/MoproKit/Example diff --git a/mopro-ffi/Cargo.toml b/mopro-ffi/Cargo.toml index 5c005d8a..5f314eb2 100644 --- a/mopro-ffi/Cargo.toml +++ b/mopro-ffi/Cargo.toml @@ -20,7 +20,7 @@ wasmer = { git = "https://github.com/oskarth/wasmer.git", rev = "09c7070" } [dependencies] mopro-core = { path = "../mopro-core" } -uniffi = { version = "0.24", features = ["cli"] } +uniffi = { version = "0.25", features = ["cli"] } serde = { version = "1", features = ["derive"] } bincode = "1" ark-serialize = { version = "=0.4.1", features = ["derive"] } @@ -34,8 +34,8 @@ color-eyre = "=0.6.2" criterion = "=0.3.6" [build-dependencies] -uniffi = { version = "0.24", features = ["build"] } +uniffi = { version = "0.25", features = ["build"] } [dev-dependencies] -uniffi = { version = "0.24", features = ["bindgen-tests"] } +uniffi = { version = "0.25", features = ["bindgen-tests"] } ark-bn254 = { version = "=0.4.0" } diff --git a/mopro-ffi/README.md b/mopro-ffi/README.md index defe1f56..ec8eb6e6 100644 --- a/mopro-ffi/README.md +++ b/mopro-ffi/README.md @@ -13,6 +13,16 @@ TBD. 1. Ensure you have Rust installed 2. Add platform targets `rustup target add x86_64-apple-ios aarch64-apple-ios aarch64-apple-ios-sim` 3. Install `uniffi-bindgen` locally with `cargo install --bin uniffi-bindgen --path .` +4. In order to locally run the bindings tests, you will need + * Kotlin: + * `kotlinc`, the [Kotlin command-line compiler](https://kotlinlang.org/docs/command-line.html). + * `ktlint`, the [Kotlin linter used to format the generated bindings](https://ktlint.github.io/). + * The [Java Native Access](https://github.com/java-native-access/jna#download) JAR downloaded and its path + added to your `$CLASSPATH` environment variable. + * Swift: + * `swift` and `swiftc`, the [Swift command-line tools](https://swift.org/download/). + * The Swift `Foundation` package. + ### Platforms supported Currently iOS is the main target, but Android will soon follow. PRs welcome. diff --git a/mopro-ffi/tests/bindings/test_mopro_keccak2.kts b/mopro-ffi/tests/bindings/test_mopro_keccak2.kts new file mode 100644 index 00000000..b7c763e6 --- /dev/null +++ b/mopro-ffi/tests/bindings/test_mopro_keccak2.kts @@ -0,0 +1,253 @@ +import uniffi.mopro.*; + +try { + initializeMopro() + + val inputs = mutableMapOf>() + inputs["in"] = + listOf( + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "1", + "0", + "1", + "0", + "0", + "1", + "1", + "0", + "1", + "1", + "0", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "1", + "0", + "1", + "1", + "1", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0", + "0" + ) + + var generateProofResult = generateProof2(inputs) + assert(generateProofResult.proof.size > 0) { "Proof is empty"} + var isValid = verifyProof2(generateProofResult.proof, generateProofResult.inputs) + // FIXME: assert(isValid) { "Proof is invalid"} + println("Proof is invalid: $isValid") +} catch (e: Exception) { + println(e); +} diff --git a/mopro-ffi/tests/bindings/test_mopro_keccak2.swift b/mopro-ffi/tests/bindings/test_mopro_keccak2.swift index 463bb8c1..a489bc98 100644 --- a/mopro-ffi/tests/bindings/test_mopro_keccak2.swift +++ b/mopro-ffi/tests/bindings/test_mopro_keccak2.swift @@ -20,30 +20,30 @@ func bytesToBits(bytes: [UInt8]) -> [String] { return bits } -// func serializeOutputs(_ stringArray: [String]) -> [UInt8] { -// var bytesArray: [UInt8] = [] -// let length = stringArray.count -// var littleEndianLength = length.littleEndian -// let targetLength = 32 -// withUnsafeBytes(of: &littleEndianLength) { -// bytesArray.append(contentsOf: $0) -// } -// for value in stringArray { -// // TODO: should handle 254-bit input -// var littleEndian = Int32(value)!.littleEndian -// var byteLength = 0 -// withUnsafeBytes(of: &littleEndian) { -// bytesArray.append(contentsOf: $0) -// byteLength = byteLength + $0.count -// } -// if byteLength < targetLength { -// let paddingCount = targetLength - byteLength -// let paddingArray = [UInt8](repeating: 0, count: paddingCount) -// bytesArray.append(contentsOf: paddingArray) -// } -// } -// return bytesArray -// } +func serializeOutputs(_ stringArray: [String]) -> [UInt8] { + var bytesArray: [UInt8] = [] + let length = stringArray.count + var littleEndianLength = length.littleEndian + let targetLength = 32 + withUnsafeBytes(of: &littleEndianLength) { + bytesArray.append(contentsOf: $0) + } + for value in stringArray { + // TODO: should handle 254-bit input + var littleEndian = Int32(value)!.littleEndian + var byteLength = 0 + withUnsafeBytes(of: &littleEndian) { + bytesArray.append(contentsOf: $0) + byteLength = byteLength + $0.count + } + if byteLength < targetLength { + let paddingCount = targetLength - byteLength + let paddingArray = [UInt8](repeating: 0, count: paddingCount) + bytesArray.append(contentsOf: paddingArray) + } + } + return bytesArray +} do { // // Setup @@ -59,25 +59,25 @@ do { var inputs = [String: [String]]() inputs["in"] = bits - // // Expected outputs - // let outputVec: [UInt8] = [ - // 37, 17, 98, 135, 161, 178, 88, 97, 125, 150, 143, 65, 228, 211, 170, 133, 153, 9, 88, - // 212, 4, 212, 175, 238, 249, 210, 214, 116, 170, 85, 45, 21, - // ] - // let outputBits: [String] = bytesToBits(bytes: outputVec) - // let expectedOutput: [UInt8] = serializeOutputs(outputBits) + // Expected outputs + let outputVec: [UInt8] = [ + 37, 17, 98, 135, 161, 178, 88, 97, 125, 150, 143, 65, 228, 211, 170, 133, 153, 9, 88, + 212, 4, 212, 175, 238, 249, 210, 214, 116, 170, 85, 45, 21, + ] + let outputBits: [String] = bytesToBits(bytes: outputVec) + let expectedOutput: [UInt8] = serializeOutputs(outputBits) // // Generate Proof let generateProofResult = try generateProof2(circuitInputs: inputs) // let generateProofResult = try moproCircom.generateProof(circuitInputs: inputs) - // assert(!generateProofResult.proof.isEmpty, "Proof should not be empty") + assert(!generateProofResult.proof.isEmpty, "Proof should not be empty") // // Verify Proof - // assert(Data(expectedOutput) == generateProofResult.inputs, "Circuit outputs mismatch the expected outputs") + assert(Data(expectedOutput) == generateProofResult.inputs, "Circuit outputs mismatch the expected outputs") let isValid = try verifyProof2( proof: generateProofResult.proof, publicInput: generateProofResult.inputs) - // assert(isValid, "Proof verification should succeed") + assert(isValid, "Proof verification should succeed") } catch let error as MoproError { print("MoproError: \(error)") diff --git a/mopro-ffi/tests/test_generated_bindings.rs b/mopro-ffi/tests/test_generated_bindings.rs index 1a770a7a..61d058ba 100644 --- a/mopro-ffi/tests/test_generated_bindings.rs +++ b/mopro-ffi/tests/test_generated_bindings.rs @@ -1,6 +1,7 @@ uniffi::build_foreign_language_testcases!( "tests/bindings/test_mopro.swift", // "tests/bindings/test_mopro.kts", + "tests/bindings/test_mopro_keccak2.kts", // "tests/bindings/test_mopro.rb", // "tests/bindings/test_mopro.py", "tests/bindings/test_mopro_keccak.swift",