Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arkworks conversion example #619

Merged
merged 24 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions examples/rust/arkworks/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,18 @@ edition = "2018"

[dependencies]
icicle-runtime = { path = "../../../wrappers/rust/icicle-runtime" }
icicle-core = { path = "../../../wrappers/rust/icicle-core" }
icicle-core = { path = "../../../wrappers/rust/icicle-core"}
icicle-bn254 = { path = "../../../wrappers/rust/icicle-curves/icicle-bn254" }
ark-bn254 = { version = "0.4.0" }
ark-ff = { version = "0.4.0" }
ark-ec = { version = "0.4.0" }
ark-bn254 = { version = "0.4.0"}
ark-ff = { version = "0.4.0" , features=["parallel"]}
ark-ec = { version = "0.4.0" , features=["parallel"]}
rand = "0.8"
rayon = "1.5"
clap = { version = "<=4.4.12", features = ["derive"] }

[features]
cuda = ["icicle-runtime/cuda_backend",
"icicle-bn254/cuda_backend",
"icicle-bn254/no_ecntt",
"icicle-bn254/no_g2",
]
60 changes: 60 additions & 0 deletions examples/rust/arkworks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@

# ICICLE Example: Arkworks and Icicle Scalar and Point Conversion

## Key Takeaway

This example demonstrates how to convert and manipulate field elements and elliptic curve points between Arkworks and ICICLE, specifically using the BN254 curve. It focuses on converting Arkworks types to ICICLE types and vice versa, ensuring seamless interaction between the two libraries.

> [!NOTE]
> Converting elements from other curves follows the same approach. Just replace the BN254 types in Arkworks and ICICLE with the corresponding types for your desired curve. The process remains the same.

> [!NOTE]
> Typically, elliptic curve points are converted once during setup and reused across multiple proofs, making conversion time less critical for these points. However, scalar values need to be converted per proof. EC point conversion is more expensive due to differences in memory layout, while scalar conversion mainly involves converting to/from Montgomery form. Future versions of ICICLE may natively support Montgomery representation for improved efficiency.

## Usage

```rust
// Generate a sequence of Arkworks scalars (e.g., [0, 1, 2, ..., size-1])
let ark_scalars = incremental_ark_scalars(size);
// Convert Arkworks scalars to ICICLE scalars
let icicle_scalars: DeviceVec<IcicleScalar> = ark_to_icicle_scalars(&ark_scalars);
// Alternatively, use transmute to reinterpret Arkworks memory as ICICLE, noting that it modifies in-place.
// Ensure you do not use the Arkworks scalars after this operation, as they are now ICICLE scalars.
let icicle_scalars: &mut [IcicleScalar] = transmute_ark_to_icicle_scalars(&mut ark_scalars);

// Generate Arkworks affine points (e.g., [g, 2*g, 3*g, ..., size*g])
let ark_affine_points = incremental_ark_affine_points(size);
// Convert Arkworks affine points to ICICLE affine points
let icicle_affine_points = ark_to_icicle_affine_points(&ark_affine_points);

// Generate Arkworks projective points (represented as Jacobian internally)
let ark_projective_points = incremental_ark_projective_points(size);
// Convert Arkworks projective points to ICICLE projective points
let icicle_projective_points = ark_to_icicle_projective_points(&ark_projective_points);
```

This example uses the `BN254` elliptic curve and showcases conversions between Arkworks and ICICLE for both affine and projective points. You can use this as a reference for other curves or use cases.

## What's in this example

1. Define the size of the dataset (scalars and points).
2. Set up the ICICLE backend (CPU or CUDA).
3. Generate incremental scalars and points using Arkworks.
4. Convert Arkworks field elements into ICICLE scalars.
5. Convert affine and projective points between Arkworks and Icicle.
6. Compute MSM (Multi-Scalar Multiplication) in both Arkworks and ICICLE, using either the CPU or CUDA backend.
7. Convert the MSM output back from ICICLE to Arkworks format and compare the results.

## Running the Example

To run the example, use the following commands based on your backend setup:

```sh
# For CPU
./run.sh -d CPU

# For CUDA
./run.sh -d CUDA -b /path/to/cuda/backend/install/dir
```

This will execute the example using either the CPU or CUDA backend, allowing you to test the conversion and computation process between Arkworks and ICICLE.
61 changes: 61 additions & 0 deletions examples/rust/arkworks/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash

# Exit immediately if a command exits with a non-zero status
set -e

# Function to display usage information
show_help() {
echo "Usage: $0 [-d DEVICE_TYPE] [-b ICICLE_BACKEND_INSTALL_DIR]"
echo
echo "Options:"
echo " -d DEVICE_TYPE Specify the device type (default: CPU)"
echo " -b ICICLE_BACKEND_INSTALL_DIR Specify the backend installation directory (default: empty)"
echo " -h Show this help message"
exit 0
}

# Parse command line options
while getopts ":d:b:h" opt; do
case ${opt} in
d )
DEVICE_TYPE=$OPTARG
;;
b )
ICICLE_BACKEND_INSTALL_DIR="$(realpath ${OPTARG})"
;;
h )
show_help
;;
\? )
echo "Invalid option: -$OPTARG" 1>&2
show_help
;;
: )
echo "Invalid option: -$OPTARG requires an argument" 1>&2
show_help
;;
esac
done

# Set default values if not provided
: "${DEVICE_TYPE:=CPU}"
: "${ICICLE_BACKEND_INSTALL_DIR:=}"

# Create necessary directories
mkdir -p build/example
mkdir -p build/icicle

ICILE_DIR=$(realpath "../../../icicle/")
ICICLE_CUDA_SOURCE_DIR="${ICILE_DIR}/backend/cuda"

# Build Icicle and the example app that links to it
if [ "$DEVICE_TYPE" == "CUDA" ] && [ ! -d "${ICICLE_BACKEND_INSTALL_DIR}" ] && [ -d "${ICICLE_CUDA_SOURCE_DIR}" ]; then
echo "Building icicle with CUDA backend"
cargo build --release --features=cuda
export ICICLE_BACKEND_INSTALL_DIR=$(realpath "./target/release/deps/icicle/lib/backend")
cargo run --release --features=cuda -- --device-type "${DEVICE_TYPE}"
else
echo "Building icicle without CUDA backend, ICICLE_BACKEND_INSTALL_DIR=${ICICLE_BACKEND_INSTALL_DIR}"
export ICICLE_BACKEND_INSTALL_DIR="$ICICLE_BACKEND_INSTALL_DIR";
cargo run --release -- --device-type "${DEVICE_TYPE}"
fi
Loading
Loading