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

Poseidon benchmark that also runs in Wasm #2633

Merged
merged 13 commits into from
Oct 11, 2024
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ idea
*.sage.py
params
_build
build
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my IDE automatically ran cmake (I think?) and added this folder, so let's gitignore it

.merlin
*.swp
*.swo
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

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

60 changes: 60 additions & 0 deletions bench-wasm.sh
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a better place for this script than the repo root?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest you create a scripts/ folder, and call this script from the Makefile, what do you think? Then it'd be similar to mina.

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/bash

# Default benchmark name
BENCH_NAME=""

# Parse the optional --bench=<NAME> argument
for i in "$@"; do
case $i in
--bench=*)
BENCH_NAME="${i#*=}"
shift # Remove --bench=<NAME> from processing
;;
*)
# unknown option
;;
esac
done

# Throw an error if --bench was not provided
if [ -z "$BENCH_NAME" ]; then
echo "Error: You must specify a benchmark using --bench=<NAME>"
exit 1
fi

# Function to delete any old .wasm files related to the current benchmark
cleanup_old_wasm_files() {
WASM_FILES=$(find target/wasm32-wasi/release/deps/ -type f -name "*$BENCH_NAME*.wasm")

if [ -n "$WASM_FILES" ]; then
echo "Cleaning up old WASM files for benchmark '$BENCH_NAME'..."
rm -f $WASM_FILES
else
echo "No old WASM files found for benchmark '$BENCH_NAME'."
fi
}

# Call the cleanup function
cleanup_old_wasm_files
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add cd $(git rev-parse --show-toplevel) or something like that? Maybe another argument that would specify from which directory to execute, so we have to pass .? This script is assumed to be called /exactly/ from a directory we need it to run into, and I think it's not a very obvious UX and can potentially erase some files you didn't expect it to touch.


# Build the WASM benchmark with cargo-wasi
echo "Building benchmark '$BENCH_NAME' with cargo-wasi..."
cargo wasi build --bench="$BENCH_NAME" --release

# Function to find the correct WASM file
find_wasm_file() {
# Search for the WASM file corresponding to the benchmark name
WASM_FILE=$(find target/wasm32-wasi/release/deps/ -type f -name "*$BENCH_NAME*.wasm" | head -n 1)

if [ -z "$WASM_FILE" ]; then
echo "Error: No WASM file found for benchmark '$BENCH_NAME'."
exit 1
fi
}

# Call the function to find the correct WASM file
find_wasm_file

echo "Running benchmark at $WASM_FILE with wasmer-js..."
# Run the WASM file with wasmer-js
wasmer-js run --dir=. "$WASM_FILE" -- --bench
10 changes: 9 additions & 1 deletion poseidon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@ ocaml-gen = { workspace = true, optional = true }
[dev-dependencies]
serde_json.workspace = true
hex.workspace = true
criterion = { version = "0.3", default-features = false, features = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it work if we put this criterion into the top level Cargo.toml? Or is this version/feature selection fundamentally incompatible with criterion used in different packages within proof-systems?

"cargo_bench_support",
"html_reports",
] }

[features]
default = []
ocaml_types = [ "ocaml", "ocaml-gen", ]
ocaml_types = ["ocaml", "ocaml-gen"]

[[bench]]
name = "poseidon_bench"
harness = false
32 changes: 31 additions & 1 deletion poseidon/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Oracle
# Poseidon

## Test vectors

Expand All @@ -17,3 +17,33 @@ cargo run -p export_test_vectors -- B10 legacy -
cargo run -p export_test_vectors -- b10 legacy legacy.json
cargo run -p export_test_vectors -- hex kimchi kimchi.json
```

## Benchmark

This folder contains a Poseidon benchmark `poseidon_bench`.

To run the benchmark natively, do:

```sh
cargo bench --bench=poseidon_bench
```

It can also be run in WebAssembly (executed by Node.js), with the following prerequisites:

- Add the `wasm32-wasi` target
- Install `cargo-wasi`
- Install the wasmer JS CLI

```sh
rustup target add wasm32-wasi
cargo install cargo-wasi
npm install -g @wasmer/cli
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh, fun, we now have the npm dependency for proof-systems.

```

Now, you can run this and other benchmarks in Wasm, using the following from the repository root:

```sh
./bench-wasm.sh --bench=poseidon_bench
```

For this to work, the filename of your benchmark has to be the same as the benchmark name!
30 changes: 30 additions & 0 deletions poseidon/benches/poseidon_bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use criterion::{criterion_group, criterion_main, Criterion};
use mina_curves::pasta::Fp;
use mina_poseidon::{
constants::PlonkSpongeConstantsKimchi,
pasta::fp_kimchi as SpongeParametersKimchi,
poseidon::{ArithmeticSponge as Poseidon, Sponge},
};

pub fn bench_poseidon_kimchi(c: &mut Criterion) {
let mut group = c.benchmark_group("Poseidon");
group.sample_size(100);

// Chain of hashes, starting from a random value
group.bench_function("poseidon_hash_kimchi", |b| {
let mut hash: Fp = rand::random();
let mut poseidon = Poseidon::<Fp, PlonkSpongeConstantsKimchi>::new(
SpongeParametersKimchi::static_params(),
);

b.iter(|| {
poseidon.absorb(&[hash]);
hash = poseidon.squeeze();
})
});

group.finish();
}

criterion_group!(benches, bench_poseidon_kimchi);
criterion_main!(benches);