# Improved Architecture for Proof Generation in Mobile: Turbo Module Update ### **Goal** To establish a single shared C++ folder for both iOS and Android platforms with bindings, improving maintainability and readability while optimizing proof generation. --- ## **Existing Solution for Rapidsnark Integration** ### **Current Steps:** 1. **Binary Generation:** We generate `rapidsnark` and witness calculation binaries for different Android and iOS architectures. 2. **Native Code Bridging:** Native code bridges are required to connect C++ code with the JS engine: - For **Android**: Using Java/Kotlin. - For **iOS**: Using Objective-C. These bridge APIs are invoked whenever a C++ function needs to be accessed. 3. **React Native Limitations:** Current React Native architecture does not natively support invoking C++ functions without these bridges. This limits readability and adds complexity. --- ## **Proposed Solution** ### **Shared C++ Folder** We plan to create a shared folder containing C++ code that works seamlessly across both iOS and Android. ### **Why:** - Enhanced readability and maintainability. - No need for writing native code. ### **Challenges:** - Android and iOS use different shared libraries. - These libraries need to be bundled correctly or specified during runtime for each platform. - How do we handle binding C++ code for various architectures into a unified system? --- --- ## **Steps to Implement** ### 1. Define a Spec File The spec file is converted using the **codegen tool**, generating files in the `/generated` folder for Android and iOS. ```typescript import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { reverseString: (str: string) => string; getNumbers: () => Array<number>; getObject: () => { [key: string]: string }; promiseNumber: (value: number) => Promise<number>; callMeLater: (successCB: () => void, failureCB: () => void) => void; } export default TurboModuleRegistry.getEnforcing<Spec>('CppTurbo'); ``` ### 2. Shared Cpp Lib 1. Header File: For declarations. 2. Main C++ Methods File: For implementations. ```cpp #include "NativeCppTurboModule.h" namespace facebook::react { NativeCppTurboModule::NativeCppTurboModule(std::shared_ptr<CallInvoker> jsInvoker) : NativeCppTurboCxxSpec(std::move(jsInvoker)) {} std::string NativeCppTurboModule::reverseString(jsi::Runtime &rt, std::string str) { std::reverse(str.begin(), str.end()); return str; } std::vector<int> NativeCppTurboModule::getNumbers(jsi::Runtime &rt) { std::vector<int> array; for (std::size_t i = 0; i < 10; ++i) { array.push_back(static_cast<int>(i)); } return array; } std::map<std::string, std::string> NativeCppTurboModule::getObject(jsi::Runtime &rt) { std::map<std::string, std::string> map; map.insert(std::make_pair("result", "success")); return map; } jsi::Value NativeCppTurboModule::promiseNumber(jsi::Runtime &rt, double number) { jsi::Function promiseConstructor = rt.global().getPropertyAsFunction(rt, "Promise"); return promiseConstructor.callAsConstructor( rt, jsi::Function::createFromHostFunction( rt, jsi::PropNameID::forAscii(rt, "promiseArg"), 2, [number](jsi::Runtime &runtime, const jsi::Value &thisValue, const jsi::Value *arguments, std::size_t count) -> jsi::Value { jsi::Function resolve = arguments[0].asObject(runtime).asFunction(runtime); resolve.call(runtime, number); return jsi::Value::undefined(); } ) ); } void NativeCppTurboModule::callMeLater(jsi::Runtime &rt, jsi::Function successCB, jsi::Function failureCB) { bool callSuccess = std::rand() % 2; if (callSuccess) { successCB.call(rt); } else { failureCB.call(rt); } } } // namespace facebook::react ``` ### 3. Android Integration Use CMakeLists.txt to load the shared folder containing C++ code. ### 4. iOS Integration Write a oneLoad() function that will be invoked by default during runtime.