Skip to content

Commit

Permalink
docs: add C++ example with cxx (xJonathanLEI#328)
Browse files Browse the repository at this point in the history
  • Loading branch information
xJonathanLEI authored Mar 14, 2023
1 parent bbdba91 commit fc64165
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 3 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --all --target ${{ matrix.target }}
args: --all --target ${{ matrix.target }} --exclude starknet-cxx

wasm-test:
name: WASM tests
Expand All @@ -91,7 +91,7 @@ jobs:
- name: Build project
run: |
cargo build --all --target wasm32-unknown-unknown
cargo build --all --target wasm32-unknown-unknown --exclude starknet-cxx
- name: Install wasm-pack
uses: actions-rs/cargo@v1
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/examples/starknet-cxx/build/
/target/
/.idea
11 changes: 10 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ members = [
"starknet-curve",
"starknet-crypto-codegen",
"examples/starknet-wasm",
"examples/starknet-cxx/starknet-cxx",
]

[package.metadata.docs.rs]
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ This workspace contains the following crates:

`starknet-rs` can be used as a WebAssembly module. Check out [this example](./examples/starknet-wasm/).

## Using `starknet-rs` from C++

`starknet-rs` can be used as a dynamic or static library from C++. Check out [this example](./examples/starknet-cxx/).

## Performance

Benchmark results for native and WebAssembly targets are available for these crates:
Expand Down
20 changes: 20 additions & 0 deletions examples/starknet-cxx/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.21)

project(starknet_rs_in_cpp CXX)

include(FetchContent)

set(CMAKE_EXPORT_COMPILE_COMMANDS true)
set(CMAKE_CXX_STANDARD 17)

FetchContent_Declare(
Corrosion
GIT_REPOSITORY https://github.com/corrosion-rs/corrosion.git
GIT_TAG master
)
FetchContent_MakeAvailable(Corrosion)

add_subdirectory(starknet-cxx)

add_executable(main main.cpp)
target_link_libraries(main PRIVATE starknet_cxx_bridge)
35 changes: 35 additions & 0 deletions examples/starknet-cxx/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Example usage of starknet-rs from C++

This is a quick demo on exposing `starknet-crypto` to C++ with the [cxx](https://github.com/dtolnay/cxx) bridge and [corrosion](https://github.com/corrosion-rs/corrosion).

## **WARNING**

As noted in the [`starknet-crypto` page](../../starknet-crypto/), you're advised to use high-level constructs exposed through `starknet-core` instead if you're not familiar with cryptographic primitives. `starknet-crypto` is chosen here considering that the C++ audience might prefer low-level libraries, but it's possible to wrap `starknet-core` as well.

## Note

This wrapper crate expose functions that operate on strings, which is bad and probably hurts performance. It's possible to make the C++ side create `FieldElement` instances and operate on those instead, which is much more idiomatic. That said, this demo wrapper crate seems to already offer decent performance.

Moreover, this crate does not implement error handling and always just panics on error, which is likely not what you want in production.

However, the goal of this crate is just to demonstrate using the library from C++, _NOT_ to create idiomatic bindings, which is way too much work to maintain as an example, and should be a project of its own.

## Running the example

With necessary toolings installed:

```console
$ mkdir build && cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make
```

It everything goes well, you should now have a `main` executable:

```console
$ ./main
pedersen_hash():
0x030e480bed5fe53fa909cc0f8c4d99b8f9f2c016be4c41e13a4848797979c662
ecdsa_sign():
0x0411494b501a98abd8262b0da1351e17899a0c4ef23dd2f96fec5ba847310b200405c3191ab3883ef2b763af35bc5f5d15b3b4e99461d70e84c654a351a7c81b
```
22 changes: 22 additions & 0 deletions examples/starknet-cxx/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "starknet_cxx_bridge/lib.h"
#include <iostream>

int main() {
auto hash = pedersen_hash(
"0x3d937c035c878245caf64531a5756109c53068da139362728feb561405371cb",
"0x208a0a10250e382e1e4bbe2880906c2791bf6275695e02fbbc6aeff9cd8b31a"
);

// WARNING: DO NOT hard code the k value in real code!! Doing so would expose the private key.
auto signature = ecdsa_sign(
"0x1",
"0x2",
"0x3"
);

std::cout << "pedersen_hash():" << "\n"
<< " " << hash.c_str() << "\n"
<< "ecdsa_sign():" << "\n"
<< " " << signature.c_str() << "\n";
return 0;
}
2 changes: 2 additions & 0 deletions examples/starknet-cxx/starknet-cxx/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
corrosion_import_crate(MANIFEST_PATH Cargo.toml)
corrosion_add_cxxbridge(starknet_cxx_bridge CRATE starknet-cxx MANIFEST_PATH starknet-cxx FILES lib.rs)
26 changes: 26 additions & 0 deletions examples/starknet-cxx/starknet-cxx/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "starknet-cxx"
version = "0.1.0"
authors = ["Jonathan LEI <[email protected]>"]
edition = "2021"

[dependencies]
cxx = "1.0"

# Using path dependency here to make development easier. However, you probably want to fetch the
# crate from crates.io instead, which means changing the next line to:
#
# starknet-crypto = "0.4.2"
starknet-crypto = { version = "0.4.2", path = "../../../starknet-crypto" }

[build-dependencies]
cxx-build = "1.0"

[lib]
crate-type = ["staticlib"]

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"
47 changes: 47 additions & 0 deletions examples/starknet-cxx/starknet-cxx/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//! This is a quick demo on exposing `starknet-crypto` to C++ with the cxx bridge:
//! https://github.com/xJonathanLEI/starknet-rs/issues/325
//!
//! This wrapper crate expose functions that operate on strings, which is bad and probably hurts
//! performance. It's possible to make the C++ side create `FieldElement` instances and operate on
//! those instead, which is much more idiomatic. That said, this demo wrapper crate seems to already
//! offer decent performance.
//!
//! Moreover, this crate does not implement error handling and always just panics on error, which
//! is likely not what you want in production.
//!
//! However, the goal of this crate is just to demonstrate using the library from C++, NOT to
//! create idiomatic bindings, which is way too much work to maintain as an example, and should be
//! a project of its own.
use starknet_crypto::{FieldElement, Signature};

#[cxx::bridge]
mod ffi {
extern "Rust" {
fn pedersen_hash(x: &str, y: &str) -> String;

fn ecdsa_sign(private_key: &str, message: &str, k: &str) -> String;
}
}

pub fn pedersen_hash(x: &str, y: &str) -> String {
// WARNING: no error handling here
let x = FieldElement::from_hex_be(x).unwrap();
let y = FieldElement::from_hex_be(y).unwrap();

format!("{:#064x}", starknet_crypto::pedersen_hash(&x, &y))
}

fn ecdsa_sign(private_key: &str, message: &str, k: &str) -> String {
// WARNING: no error handling here
let private_key = FieldElement::from_hex_be(private_key).unwrap();
let message = FieldElement::from_hex_be(message).unwrap();
let k = FieldElement::from_hex_be(k).unwrap();

let signature: Signature = starknet_crypto::sign(&private_key, &message, &k)
// WARNING: no error handling here
.unwrap()
.into();

format!("0x{signature}")
}

0 comments on commit fc64165

Please sign in to comment.