Skip to content

Commit b9704b4

Browse files
Use NIF instead of WASM to gain performances
1 parent 41a5819 commit b9704b4

38 files changed

+879
-557
lines changed

.DS_Store

-6 KB
Binary file not shown.

.github/workflows/release.yml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
name: Build precompiled NIFs
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
tags:
8+
- "*"
9+
10+
jobs:
11+
build_release:
12+
name: NIF ${{ matrix.nif }} - ${{ matrix.job.target }} (${{ matrix.job.os }})
13+
runs-on: ${{ matrix.job.os }}
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
nif: ["2.16", "2.17"]
18+
job:
19+
- {
20+
target: arm-unknown-linux-gnueabihf,
21+
os: ubuntu-20.04,
22+
use-cross: true,
23+
}
24+
- {
25+
target: aarch64-unknown-linux-gnu,
26+
os: ubuntu-20.04,
27+
use-cross: true,
28+
}
29+
- {
30+
target: aarch64-unknown-linux-musl,
31+
os: ubuntu-20.04,
32+
use-cross: true,
33+
}
34+
- { target: aarch64-apple-darwin, os: macos-14 }
35+
- {
36+
target: riscv64gc-unknown-linux-gnu,
37+
os: ubuntu-20.04,
38+
use-cross: true,
39+
}
40+
- { target: x86_64-apple-darwin, os: macos-14 }
41+
- { target: x86_64-unknown-linux-gnu, os: ubuntu-20.04 }
42+
- {
43+
target: x86_64-unknown-linux-musl,
44+
os: ubuntu-20.04,
45+
use-cross: true,
46+
}
47+
- { target: x86_64-pc-windows-gnu, os: windows-2019 }
48+
- { target: x86_64-pc-windows-msvc, os: windows-2019 }
49+
50+
steps:
51+
- name: Checkout source code
52+
uses: actions/checkout@v3
53+
54+
- name: Extract project version
55+
shell: bash
56+
run: |
57+
# Get the project version from mix.exs
58+
echo "PROJECT_VERSION=$(grep 'version:' mix.exs | cut -d '"' -f2)" >> $GITHUB_ENV
59+
60+
- name: Install Rust toolchain
61+
uses: dtolnay/rust-toolchain@stable
62+
with:
63+
toolchain: stable
64+
target: ${{ matrix.job.target }}
65+
66+
- name: Build the project
67+
id: build-crate
68+
uses: philss/rustler-precompiled-action@v1.0.1
69+
with:
70+
project-name: bls
71+
project-version: ${{ env.PROJECT_VERSION }}
72+
target: ${{ matrix.job.target }}
73+
nif-version: ${{ matrix.nif }}
74+
use-cross: ${{ matrix.job.use-cross }}
75+
project-dir: "native/bls"
76+
77+
- name: Artifact upload
78+
uses: actions/upload-artifact@v3
79+
with:
80+
name: ${{ steps.build-crate.outputs.file-name }}
81+
path: ${{ steps.build-crate.outputs.file-path }}
82+
83+
- name: Publish archives and packages
84+
uses: softprops/action-gh-release@v1
85+
with:
86+
files: |
87+
${{ steps.build-crate.outputs.file-path }}
88+
if: startsWith(github.ref, 'refs/tags/')

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,5 @@ bls_ex-*.tar
2424

2525
# Temporary files, for example, from tests.
2626
/tmp/
27+
28+
.DS_Store

config/config.exs

Lines changed: 0 additions & 4 deletions
This file was deleted.

lib/bls_ex.ex

Lines changed: 61 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,80 @@
11
defmodule BlsEx do
22
@moduledoc """
3-
BlsEx provides utility to leverage BLS signatures through WASM
4-
"""
5-
alias __MODULE__.Keystore
3+
BlsEx provides utility to leverage BLS signatures
64
7-
@doc """
8-
Verifies a single BLS signature
5+
BLS scheme supports aggregation of public keys and aggregation of signatures.
96
10-
## Examples
7+
Here an full example of aggregated signature verification
118
12-
iex> {:ok, pid} = BlsEx.Keystore.start_link(seed: "myseed")
13-
iex> {:ok, public_key} = BlsEx.Keystore.get_public_key(pid)
14-
iex> {:ok, signature} = BlsEx.Keystore.sign(pid, "hello")
15-
iex> BlsEx.verify_signature(public_key, "hello", signature)
16-
{:ok, true}
9+
iex> seed = :crypto.hash(:sha512, "myseed")
10+
iex> public_key1 = BlsEx.get_public_key(seed)
11+
iex> signature1 = BlsEx.sign(seed, "hello")
12+
iex> seed2 = :crypto.hash(:sha512, "myseed2")
13+
iex> public_key2 = BlsEx.get_public_key(seed2)
14+
iex> signature2 = BlsEx.sign(seed2, "hello")
15+
iex> aggregated_signature = BlsEx.aggregate_signatures([signature1, signature2], [public_key1, public_key2])
16+
iex> aggregated_public_key = BlsEx.aggregate_public_keys([public_key1, public_key2])
17+
iex> BlsEx.verify_signature(aggregated_public_key, "hello", aggregated_signature)
18+
true
1719
"""
18-
@spec verify_signature(public_key :: binary(), message :: binary(), signature :: binary()) ::
19-
{:ok, boolean()} | {:error, any()}
20-
defdelegate verify_signature(public_key, message, signature), to: __MODULE__.StandaloneWasm
2120

22-
@doc """
23-
Aggregate BLS signatures
21+
@version Mix.Project.config()[:version]
2422

25-
## Examples
23+
use RustlerPrecompiled,
24+
otp_app: :bls_ex,
25+
crate: "bls",
26+
base_url: "https://github.com/archethic-foundation/bls_ex/releases/download/#{@version}",
27+
force_build: System.get_env("BLS_EX_BUILD") in ["1", "true"],
28+
targets:
29+
Enum.uniq(["aarch64-unknown-linux-musl" | RustlerPrecompiled.Config.default_targets()]),
30+
version: @version
2631

27-
iex> {:ok, pid} = BlsEx.Keystore.start_link(seed: "myseed")
28-
iex> {:ok, public_key1} = BlsEx.Keystore.get_public_key(pid)
29-
iex> {:ok, signature1} = BlsEx.Keystore.sign(pid, "hello")
30-
iex> {:ok, pid2} = BlsEx.Keystore.start_link(seed: "myseed2")
31-
iex> {:ok, public_key2} = BlsEx.Keystore.get_public_key(pid2)
32-
iex> {:ok, signature2} = BlsEx.Keystore.sign(pid2, "hello")
33-
iex> BlsEx.aggregate_signatures([signature1, signature2], [public_key1, public_key2])
34-
"""
35-
@spec aggregate_signatures(signatures :: list(binary()), public_keys :: list(binary())) ::
36-
{:ok, binary()} | {:error, any()}
37-
defdelegate aggregate_signatures(signatures, public_keys), to: __MODULE__.StandaloneWasm
32+
@type secret_key :: <<_::512>>
33+
@type signature :: <<_::96>>
34+
@type public_key :: <<_::48>>
3835

3936
@doc """
40-
Aggregate BLS public keys
41-
42-
## Examples
37+
Generate a public key from a secret key
38+
"""
39+
@spec get_public_key(secret_key :: secret_key()) :: public_key()
40+
def get_public_key(secret_key) when is_binary(secret_key) and byte_size(secret_key) == 512,
41+
do: :erlang.nif_error(:nif_not_loaded)
4342

44-
iex> {:ok, pid} = BlsEx.Keystore.start_link(seed: "myseed")
45-
iex> {:ok, public_key1} = BlsEx.Keystore.get_public_key(pid)
46-
iex> {:ok, pid2} = BlsEx.Keystore.start_link(seed: "myseed2")
47-
iex> {:ok, public_key2} = BlsEx.Keystore.get_public_key(pid2)
48-
iex> {:ok, _aggregated_public_key} = BlsEx.aggregated_public_keys([public_key1, public_key2])
43+
@doc """
44+
Sign a message using the given secret key
4945
"""
50-
@spec aggregated_public_keys(public_keys :: list(binary())) :: {:ok, binary()} | {:error, any()}
51-
defdelegate aggregated_public_keys(public_keys), to: __MODULE__.StandaloneWasm
46+
@spec sign(secret_key :: secret_key(), message :: binary()) :: signature()
47+
def sign(secret_key, data)
48+
when is_binary(secret_key) and byte_size(secret_key) == 512 and is_binary(data),
49+
do: :erlang.nif_error(:nif_not_loaded)
5250

5351
@doc """
54-
Verifies an aggregated BLS signature
52+
Verifies a single BLS signature
53+
"""
54+
@spec verify_signature(
55+
public_key :: public_key(),
56+
message :: binary(),
57+
signature :: signature()
58+
) ::
59+
boolean()
60+
def verify_signature(public_key, message, signature)
61+
when is_binary(public_key) and byte_size(public_key) == 48 and is_binary(message) and
62+
is_binary(signature) and byte_size(signature) == 96,
63+
do: :erlang.nif_error(:nif_not_loaded)
5564

56-
## Examples
65+
@doc """
66+
Aggregate a list of signatures
67+
"""
68+
@spec aggregate_signatures(list(signature()), list(public_key())) :: signature()
69+
def aggregate_signatures(signatures, public_keys)
70+
when is_list(signatures) and is_list(public_keys) and
71+
length(signatures) == length(public_keys),
72+
do: :erlang.nif_error(:nif_not_loaded)
5773

58-
iex> {:ok, pid} = BlsEx.Keystore.start_link(seed: "myseed")
59-
iex> {:ok, public_key1} = BlsEx.Keystore.get_public_key(pid)
60-
iex> {:ok, signature1} = BlsEx.Keystore.sign(pid, "hello")
61-
iex> {:ok, pid2} = BlsEx.Keystore.start_link(seed: "myseed2")
62-
iex> {:ok, public_key2} = BlsEx.Keystore.get_public_key(pid2)
63-
iex> {:ok, signature2} = BlsEx.Keystore.sign(pid2, "hello")
64-
iex> {:ok, aggregated_signature} = BlsEx.aggregate_signatures([signature1, signature2], [public_key1, public_key2])
65-
iex> BlsEx.verify_aggregated_signature( [public_key1, public_key2], "hello", aggregated_signature)
66-
{:ok, true}
74+
@doc """
75+
Aggregate a list of public keys
6776
"""
68-
@spec verify_aggregated_signature(list(binary()), binary(), binary()) ::
69-
{:ok, boolean()} | {:error, any()}
70-
defdelegate verify_aggregated_signature(public_keys, message, signature),
71-
to: __MODULE__.StandaloneWasm
77+
@spec aggregate_public_keys(list(public_key())) :: public_key()
78+
def aggregate_public_keys(public_keys) when is_list(public_keys),
79+
do: :erlang.nif_error(:nif_not_loaded)
7280
end

lib/bls_ex/application.ex

Lines changed: 0 additions & 13 deletions
This file was deleted.

lib/bls_ex/keystore.ex

Lines changed: 0 additions & 97 deletions
This file was deleted.

0 commit comments

Comments
 (0)