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

ZAL: ZK Accel Layer #308

Merged
merged 24 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9dea740
zal: export MSM and threadpool to C DLL
mratsim Dec 1, 2023
28931d6
fix LTO spurious warnings when building library
mratsim Dec 1, 2023
14634c6
fix appType staticLib vs staticlib
mratsim Dec 1, 2023
1db3574
fix threadpool
mratsim Dec 1, 2023
9aad9a0
shorter EC FFI
mratsim Dec 1, 2023
4c479cf
zal: now compiles with halo2curves and can call Nim
mratsim Dec 1, 2023
a0e358c
zal: Pass tests
mratsim Dec 1, 2023
5fe449c
zal: add benches Halo2curves vs Constantine
mratsim Dec 2, 2023
d439117
CI: add constantine-rust / ZAL to CI
mratsim Dec 2, 2023
2f23497
CI: can't use variables for shell
mratsim Dec 2, 2023
23ee652
CI: display rust version
mratsim Dec 2, 2023
ddc06f8
Rust: force clang for building (Rust regression following #309 remova…
mratsim Dec 2, 2023
c31ab84
LLVM (hence llvm-config) isn't installed in Github Actions CI
mratsim Dec 2, 2023
877888f
documentation of compile options
mratsim Dec 2, 2023
330a65e
reduce rust verbosity
mratsim Dec 2, 2023
0c0bc25
cargo in CI, spray and pray
mratsim Dec 2, 2023
f7d4235
don't update Rust twice
mratsim Dec 2, 2023
cce7236
if using clang, Nim expects llvm-ar for static libraries archiver
mratsim Dec 2, 2023
d7b8668
Expose full LLVM on MacOS, no Rust for i386, CPU features
mratsim Dec 3, 2023
7563a21
fix HW info
mratsim Dec 3, 2023
143fd8c
the light at the end of the CI tunnel
mratsim Dec 3, 2023
9d5e621
ensure autoloading kernel32.dll threading API
mratsim Dec 3, 2023
0dfe2e4
Keep stack guard pages on Windows
mratsim Dec 4, 2023
231ccc7
MacOS CI: some agents don't support ADX instructions and SIGILL
mratsim Dec 4, 2023
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
4 changes: 2 additions & 2 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@
# if the base LLVM versions differ.
# For example before LLVM 15 opaque pointers in IR triggered an error.

[build]
# https://doc.rust-lang.org/rustc/linker-plugin-lto.html
# [build]
# # https://doc.rust-lang.org/rustc/linker-plugin-lto.html
# rustflags="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld"
121 changes: 92 additions & 29 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ jobs:
max-parallel: 20
matrix:
nim_version: [version-1-6] # [version-1-4, devel]
rust_toolchain: [stable] # [beta, nightly]
target:
- os: linux
cpu: i386
Expand Down Expand Up @@ -157,10 +158,12 @@ jobs:
run: |
sudo DEBIAN_FRONTEND='noninteractive' apt-fast install \
--no-install-recommends -yq \
libgmp-dev
libgmp-dev \
llvm

- name: Install test dependencies (Linux i386)
if: runner.os == 'Linux' && matrix.target.cpu == 'i386'
# We don't install LLVM as the Rust libraries that call Constantine are 64-bit only.
run: |
sudo dpkg --add-architecture i386
sudo apt-fast update -qq
Expand Down Expand Up @@ -198,18 +201,20 @@ jobs:

# Furthermore, Apple Clang can delete symbols when building a static library
# in particular the hasAdxImpl bool for CPU runtime detection.
run: |
mkdir -p external/bin
cat << EOF > external/bin/clang
#!/bin/bash
exec $(brew --prefix llvm@15)/bin/clang "\$@"
EOF
cat << EOF > external/bin/clang++
#!/bin/bash
exec $(brew --prefix llvm@15)/bin/clang++ "\$@"
EOF
chmod 755 external/bin/{clang,clang++}
echo '${{ github.workspace }}/external/bin' >> $GITHUB_PATH

# run: |
# mkdir -p external/bin
# cat << EOF > external/bin/clang
# #!/bin/bash
# exec $(brew --prefix llvm@15)/bin/clang "\$@"
# EOF
# cat << EOF > external/bin/clang++
# #!/bin/bash
# exec $(brew --prefix llvm@15)/bin/clang++ "\$@"
# EOF
# chmod 755 external/bin/{clang,clang++}
# echo '${{ github.workspace }}/external/bin' >> $GITHUB_PATH
run: echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH

- name: Setup MSYS2 (Windows)
if: runner.os == 'Windows'
Expand All @@ -223,7 +228,7 @@ jobs:
if: runner.os == 'Windows'
shell: msys2 {0}
run: |
pacman -S --needed --noconfirm mingw-w64-x86_64-gmp
pacman -S --needed --noconfirm mingw-w64-x86_64-gmp mingw-w64-x86_64-llvm
nimble refresh --verbose -y
nimble install --verbose -y gmp jsony asynctools yaml@1.1.0

Expand All @@ -234,50 +239,108 @@ jobs:
nimble refresh --verbose -y
nimble install --verbose -y gmp jsony asynctools yaml@1.1.0

- name: Print Nim & compiler versions
- name: Install Rust
shell: bash
# gcc is an alias to Clang on MacOS
run: rustup update ${{ matrix.rust_toolchain }} && rustup default ${{ matrix.rust_toolchain }}

- name: Print Nim, Rust, LLVM versions and CPU specs.
shell: bash
# gcc is an alias to Apple Clang on MacOS
run: |
nim -v
gcc -v
clang -v
rustup --version
if [[ '${{ matrix.target.cpu }}' != 'i386' && '${{ runner.os }}' != 'Windows' ]]; then
llvm-config --version
fi
if [[ '${{ runner.os }}' == 'Linux' ]]; then
cat /proc/cpuinfo
fi
if [[ '${{ runner.os }}' == 'macOS' ]]; then
sysctl -a | grep machdep.cpu
sysctl -a | grep hw | grep cpu
sysctl -a | grep hw.optional
fi

- name: Run Constantine tests (UNIX with Assembly)
- name: Run Constantine as C library tests (UNIX with Assembly)
if: runner.os != 'Windows' && matrix.target.BACKEND == 'ASM'
shell: bash
run: |
cd constantine
nimble make_lib --verbose
nimble make_headers --verbose
nimble test_lib --verbose
- name: Run Constantine as C library tests (UNIX no Assembly)
if: runner.os != 'Windows' && matrix.target.BACKEND == 'NO_ASM'
shell: bash
run: |
cd constantine
CTT_ASM=0 nimble make_lib --verbose
nimble make_headers --verbose
nimble test_lib --verbose
- name: Run Constantine as C library tests (Windows with Assembly)
# So "test_bindings" uses C and can find GMP
# but nim-gmp cannot find GMP on Windows CI
if: runner.os == 'Windows' && matrix.target.BACKEND == 'ASM'
shell: msys2 {0}
run: |
cd constantine
nimble make_lib --verbose
nimble make_headers --verbose
nimble test_lib --verbose
- name: Run Constantine as C library tests (Windows no Assembly)
# So "test_bindings" uses C and can find GMP
# but nim-gmp cannot find GMP on Windows CI
if: runner.os == 'Windows' && matrix.target.BACKEND == 'NO_ASM'
shell: msys2 {0}
run: |
cd constantine
CTT_ASM=0 nimble make_lib --verbose
nimble make_headers --verbose
nimble test_lib --verbose

- name: Run Constantine as Rust library tests (with Assembly)
if: matrix.target.BACKEND == 'ASM' && matrix.target.cpu != 'i386'
shell: bash
# We need to deactivate the assembly (used by default for benches)
run: |
cd constantine
cargo test --no-default-features halo2curves --features halo2curves/multicore
- name: Run Constantine as Rust library tests (NO Assembly)
if: matrix.target.BACKEND == 'NO_ASM' && matrix.target.cpu != 'i386'
shell: bash
# We need to deactivate the assembly (used by default for benches)
run: |
cd constantine
CTT_ASM=0 cargo test --no-default-features halo2curves --features halo2curves/multicore

- name: Run Constantine in-depth tests (Unix - with GMP, with Assembly)
if: runner.os != 'Windows' && matrix.target.BACKEND == 'ASM'
shell: bash
run: |
cd constantine
nimble test_parallel --verbose
- name: Run Constantine tests (UNIX no Assembly)
- name: Run Constantine in-depth tests (Unix - with GMP, no Assembly)
if: runner.os != 'Windows' && matrix.target.BACKEND == 'NO_ASM'
shell: bash
run: |
cd constantine
CTT_ASM=0 nimble make_lib --verbose
nimble make_headers --verbose
nimble test_lib --verbose
CTT_ASM=0 nimble test_parallel --verbose
- name: Run Constantine tests (Windows with Assembly)

- name: Run Constantine in-depth tests (Windows - no GMP, with Assembly)
# So "test_bindings" uses C and can find GMP
# but nim-gmp cannot find GMP on Windows CI
if: runner.os == 'Windows' && matrix.target.BACKEND == 'ASM'
shell: msys2 {0}
run: |
cd constantine
nimble make_lib --verbose
nimble make_headers --verbose
nimble test_lib --verbose
nimble test_parallel_no_gmp --verbose
- name: Run Constantine tests (Windows no Assembly)
- name: Run Constantine in-depth tests (Windows - no GMP, no Assembly)
# So "test_bindings" uses C and can find GMP
# but nim-gmp cannot find GMP on Windows CI
if: runner.os == 'Windows' && matrix.target.BACKEND == 'NO_ASM'
shell: msys2 {0}
run: |
cd constantine
CTT_ASM=0 nimble make_lib --verbose
nimble make_headers --verbose
nimble test_lib --verbose
CTT_ASM=0 nimble test_parallel_no_gmp --verbose
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ build/
*.so.*
*.dylib
*.a
*.lib
*.la
*.dll
*.exe
Expand Down
14 changes: 9 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
resolver = "2"
members = [
"constantine-rust/constantine-sys",
"constantine-rust/ctt-curve-bls12-381",
"constantine-rust/ctt-curve-bn254-snarks",
"constantine-rust/ctt-curve-pasta",
"constantine-rust/ctt-proto-ethereum-bls-signatures",
"constantine-rust/constantine-zal-halo2kzg",
]

# If Nim static library is compiled with Clang ThinLTO, enable it on Rust side
Expand All @@ -26,4 +23,11 @@ members = [
# lto = "thin"
#
# [profile.bench]
# lto = "thin"
# lto = "thin"

[profile.bench]
opt-level = 3
debug = false
debug-assertions = false
overflow-checks = false
codegen-units = 1
2 changes: 1 addition & 1 deletion bindings/c_curve_decls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ template genBindings_EC_ShortW_Affine*(ECP, Field: untyped) =

{.pop.}

template genBindings_EC_ShortW_NonAffine*(ECP, ECP_Aff, Field: untyped) =
template genBindings_EC_ShortW_NonAffine*(ECP, ECP_Aff: untyped) =
when appType == "lib":
{.push noconv, dynlib, exportc, raises: [].} # No exceptions allowed
else:
Expand Down
55 changes: 55 additions & 0 deletions bindings/c_curve_decls_parallel.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Constantine
# Copyright (c) 2018-2019 Status Research & Development GmbH
# Copyright (c) 2020-Present Mamy André-Ratsimbazafy
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.

import
../constantine/math/config/curves,
../constantine/curves_primitives_parallel,
../constantine/platforms/allocs,
../constantine/threadpool

export curves_primitives_parallel

template genParallelBindings_EC_ShortW_NonAffine*(ECP, ECP_Aff, ScalarField: untyped) =
# For some unknown reason {.push noconv.}
# would overwrite the threadpool {.nimcall.}
# in the parallel for-loop `generateClosure`
#
# Similarly, exportc breaks the threadpool generated closure
# hence instead of push/pop we create a pragma alias

when appType == "lib":
{.pragma: libExport, dynlib, exportc, raises: [].} # No exceptions allowed
else:
{.pragma: libExport, exportc, raises: [].} # No exceptions allowed

# --------------------------------------------------------------------------------------
proc `ctt _ ECP _ multi_scalar_mul_big_coefs_vartime_parallel`(
tp: Threadpool,
r: var ECP,
coefs: ptr UncheckedArray[BigInt[ECP.F.C.getCurveOrderBitwidth()]],
points: ptr UncheckedArray[ECP_Aff],
len: csize_t) {.libExport.} =
tp.multiScalarMul_vartime_parallel(r.addr, coefs, points, cast[int](len))

proc `ctt _ ECP _ multi_scalar_mul_fr_coefs_vartime_parallel`(
tp: Threadpool,
r: var ECP,
coefs: ptr UncheckedArray[ScalarField],
points: ptr UncheckedArray[ECP_Aff],
len: csize_t) {.libExport.} =

let n = cast[int](len)
let coefs_fr = allocHeapArrayAligned(matchingOrderBigInt(ECP.F.C), n, alignment = 64)

syncScope:
tp.parallelFor i in 0 ..< n:
captures: {coefs, coefs_fr}
coefs_fr[i].fromField(coefs[i])
tp.multiScalarMul_vartime_parallel(r.addr, coefs_fr, points, n)

freeHeapAligned(coefs_fr)
Loading
Loading