Skip to content

Commit

Permalink
docs: restructure documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
nikgraf committed Feb 17, 2024
1 parent 1dbe9e4 commit b8b9937
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 85 deletions.
91 changes: 91 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@ Contributions are always welcome, no matter how large or small!

We want this community to be friendly and respectful to each other. Please follow it in all your interactions with the project. Before contributing, please read the [code of conduct](./CODE_OF_CONDUCT.md).

## Rust Setup

```bash
cd rust
cargo install cxxbridge-cmd # (if not installed already)
rustup target add x86_64-apple-ios aarch64-apple-ios aarch64-apple-ios-sim # (if on macOS and not installed already)
rustup target add i686-linux-android x86_64-linux-android aarch64-linux-android arm-linux-androideabi # (if not installed already)
./build-all.sh # (inside the rust directory)
```

To pass additional arguments to cargo you can set the `EXTRA_ARGS` env variable.
For example, to do a release build with p256 feature:

```bash
EXTRA_ARGS="--features p256" ./build-all.sh
```

We use the cxx crate to generate the glue code to expose a C++ interface from rust.
The cxx crate itself includes a C++ build step in its own build script.
Unfortunately cross-compilation for Android requires special care to use the NDK toolchain and it is currently not possible to set up target specific environment variables in a cargo config.
Therefore the rust project needs to be built with a separate build script `build-all.sh` (or `build-all.bat` on Windows).

Since the C++ code generated by cxx further needs to be included by our XCode or Gradle+CMake build we use the `rust/gen-cxx.sh` script to invoke the `cxxbridge` command to generate the C++ source.
This requires the `cxxbridge-cmd` cargo package to be installed (`cargo install cxxbridge-cmd`).
Note that the `gen-cxx` script will be run at the end of `build-all` so you don't need to run it manually.

## Development workflow

To get started with the project, run `yarn` in the root directory to install the required dependencies for each package:
Expand Down Expand Up @@ -64,6 +90,63 @@ To edit the Objective-C or Swift files, open `example/ios/OpaqueExample.xcworksp

To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `react-native-opaque` under `Android`.

## File Structure

Directory overview:

```
/
cpp/
opaque-rust.cpp # generated from cxxbridge
opaque-rust.h
react-native-opaque.cpp # JSI bindings for the opaque_rust C++ interface
react-native-opaque.h
rust/
src/lib.rs # Rust source
build-android.{sh,bat} # Build library for given android target
build-all.{sh,bat} # Build all targets (only android on windows)
gen-cxx.{sh,bat} # Generate cxx source
android/
CMakeLists.txt # the build config where we set up the C++ source and link with the Rust lib
cpp-adapter.cpp # defines the JNI "initialize" function which installs opaque JSI functions
react-native-opaque.podspec # build config for iOS to include the C++ and link with Rust lib
```

### iOS Build

The podspec uses the `pod_target_xcconfig` setting to set up appropriate `LIBRARY_SEARCH_PATHS` and `LIBTOOLFLAGS` to link with the rust library and includes the `ios/` and `cpp/` source in the build.

After the rust library is built you can run

```bash
yarn example ios
```

as usual in the project root to build and run the iOS example app.

### Android Build

The `CMakeLists.txt` includes the `cpp/` source and links with the appropriate rust library target depending on the target arch.

After the rust library is built you can run

```bash
# list our emulators e.g. emulator -list-avds
# start the emulator e.g. emulator @Pixel_3a_API_33_arm64-v8a
yarn example android
```

as usual in the project root to build and run the Android example app.

### Module initialization

On both iOS and Android we define a react native module with a single `install` function (`ios/Opaque.mm` and `android/src/main/java/com/opaque/OpaqueModule.java`).
This install function is called when the module is imported on the JavaScript side which then calls the `installOpaque` function (in `cpp/react-native-opaque.cpp`) to register the opaque JSI functions.
On Android we need the additional `cpp-adapter.cpp` which defines a JNI function `initialize` which can be called from the Java side to indirectly call the `installOpaque` function on the native C++ side.

### Commit message convention

We follow the [conventional commits specification](https://www.conventionalcommits.org/en) for our commit messages:
Expand Down Expand Up @@ -95,6 +178,14 @@ To publish new versions, run the following:
yarn release
```

### P256 Release

Follow these steps:

1. Sync the fork at [https://github.com/serenity-kit/react-native-opaque-p256](https://github.com/serenity-kit/react-native-opaque-p256)
2. Run the built script with `EXTRA_ARGS="--features p256" ./build-all.sh`
3. Run `yarn publish` to publish the new version to npm.

### Scripts

The `package.json` file contains various scripts for common tasks:
Expand Down
95 changes: 10 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ npm install react-native-opaque
```js
import * as opaque from 'react-native-opaque';

const { clientRegistration, registrationRequest } =
opaque.clientRegistrationStart('hunter2');
const password = 'sup-krah.42-UOI'; // user password

const { clientRegistrationState, registrationRequest } =
opaque.client.startRegistration({ password });
// ...
```

Expand All @@ -25,9 +27,11 @@ Since on web the package uses Web Assembly under the hood, it needs to be loaded
```ts
import * as opaque from 'react-native-opaque';

const password = 'sup-krah.42-UOI'; // user password

opaque.ready.then(() => {
const { clientRegistration, registrationRequest } =
opaque.clientRegistrationStart('hunter2');
const { clientRegistrationState, registrationRequest } =
opaque.client.startRegistration({ password });
// ...
});
```
Expand Down Expand Up @@ -66,88 +70,9 @@ export default function LoadingApp() {

Note: The `ready` Promise resolves right away on the native side.

## Build Setup

Directory overview:

```
/
cpp/
opaque-rust.cpp # generated from cxxbridge
opaque-rust.h
react-native-opaque.cpp # JSI bindings for the opaque_rust C++ interface
react-native-opaque.h
rust/
src/lib.rs # Rust source
build-android.{sh,bat} # Build library for given android target
build-all.{sh,bat} # Build all targets (only android on windows)
gen-cxx.{sh,bat} # Generate cxx source
android/
CMakeLists.txt # the build config where we set up the C++ source and link with the Rust lib
cpp-adapter.cpp # defines the JNI "initialize" function which installs opaque JSI functions
react-native-opaque.podspec # build config for iOS to include the C++ and link with Rust lib
```

### Rust Build

```bash
cd rust
cargo install cxxbridge-cmd # (if not installed already)
rustup target add x86_64-apple-ios aarch64-apple-ios aarch64-apple-ios-sim # (if on macOS and not installed already)
rustup target add i686-linux-android x86_64-linux-android aarch64-linux-android arm-linux-androideabi # (if not installed already)
./build-all.sh # (inside the rust directory)
```

To pass additional arguments to cargo you can set the `EXTRA_ARGS` env variable.
For example, to do a release build with p256 feature:

```bash
EXTRA_ARGS="--feature p256" ./build-all.sh
```

We use the cxx crate to generate the glue code to expose a C++ interface from rust.
The cxx crate itself includes a C++ build step in its own build script.
Unfortunately cross-compilation for Android requires special care to use the NDK toolchain and it is currently not possible to set up target specific environment variables in a cargo config.
Therefore the rust project needs to be built with a separate build script `build-all.sh` (or `build-all.bat` on Windows).

Since the C++ code generated by cxx further needs to be included by our XCode or Gradle+CMake build we use the `rust/gen-cxx.sh` script to invoke the `cxxbridge` command to generate the C++ source.
This requires the `cxxbridge-cmd` cargo package to be installed (`cargo install cxxbridge-cmd`).
Note that the `gen-cxx` script will be run at the end of `build-all` so you don't need to run it manually.

### iOS Build

The podspec uses the `pod_target_xcconfig` setting to set up appropriate `LIBRARY_SEARCH_PATHS` and `LIBTOOLFLAGS` to link with the rust library and includes the `ios/` and `cpp/` source in the build.

After the rust library is built you can run

```bash
yarn example ios
```

as usual in the project root to build and run the iOS example app.

### Android Build

The `CMakeLists.txt` includes the `cpp/` source and links with the appropriate rust library target depending on the target arch.

After the rust library is built you can run

```bash
# list our emulators e.g. emulator -list-avds
# start the emulator e.g. emulator @Pixel_3a_API_33_arm64-v8a
yarn example android
```

as usual in the project root to build and run the Android example app.

### Module initialization
## Documentation

On both iOS and Android we define a react native module with a single `install` function (`ios/Opaque.mm` and `android/src/main/java/com/opaque/OpaqueModule.java`).
This install function is called when the module is imported on the JavaScript side which then calls the `installOpaque` function (in `cpp/react-native-opaque.cpp`) to register the opaque JSI functions.
On Android we need the additional `cpp-adapter.cpp` which defines a JNI function `initialize` which can be called from the Java side to indirectly call the `installOpaque` function on the native C++ side.
In depth documentation can be found at [https://opaque-documentation.netlify.app/](https://opaque-documentation.netlify.app/).

## Contributing

Expand Down

0 comments on commit b8b9937

Please sign in to comment.