#elliptic-curves #pairing #substrate

no-std sp-ark-models

A substrate replacement model for bls12 of ark-ec

3 releases

0.4.1-beta Sep 1, 2023
0.4.0 Feb 10, 2023
0.4.0-beta May 16, 2023

#115 in Cryptography

Download history 657/week @ 2023-05-31 3935/week @ 2023-06-07 5843/week @ 2023-06-14 4981/week @ 2023-06-21 4592/week @ 2023-06-28 4204/week @ 2023-07-05 5367/week @ 2023-07-12 4002/week @ 2023-07-19 5350/week @ 2023-07-26 3363/week @ 2023-08-02 3795/week @ 2023-08-09 4604/week @ 2023-08-16 14591/week @ 2023-08-23 20806/week @ 2023-08-30 18252/week @ 2023-09-06 16978/week @ 2023-09-13

71,466 downloads per month
Used in 6 crates

MIT/Apache

15KB
343 lines

ark-substrate

Overview

Disclaimer: Please understand that this is still work based on a WIP PR of Substrate and a pre-release of arkworks-rs/algebra 0.4.0 and not ready to be used in production.

Library to integrate arkworks-rs/algebra into Substrate. This is a partial fork of the code from arkworks-rs/algebra and arkworks-rs/curves. We fork the popular elliptic curves BLS12_381, BLS12_377, BW6_761, ED_ON_BLS12_381_BANDERSNATCH and ED_ON_BLS12_377 in a way which allows us to replace the elliptic curve arithmetic which is usally slow in WASM by host funciton calls into binary code.

We also provide forks of the models BW6 and BLS12. The reason for this is that we want to avoid the point preparation in the Substrate runtime. Therefore we re-define the elliptic curve sub-groups G2 for both models as thin wrappers around the affine points and move the point preparation procedure to the host function site.

The "ready to go" end-user implementations of the Arkworks equivalent elliptic curves are in substrate-curves.

Benchmark results

extrinsic arkworkrs(µs)[^1] ark-substrate(µs)[^2] speedup[^3] dummy(µs)[^4] native(µs)[^5]
groth16_verification (bls12_381) 23335.84 3569.35 ${\color{green}\bf 6.54 \boldsymbol{\times}}$ 190.80 3440
bls12_381_pairing 9092.61 1390.80 ${\color{green}\bf 6.54 \boldsymbol{\times}}$ 24.64 1270
bls12_381_msm_g1, 10 arguments 6921.99 949.58 ${\color{green}\bf 7.29 \boldsymbol{\times}}$ 50.07 568.89
bls12_381_msm_g1, 1000 arguments 194969.80 30158.23 ${\color{green}\bf 6.46 \boldsymbol{\times}}$ 2169.47 10750
bls12_381_msm_g2, 10 arguments 21513.87 2870.33 ${\color{green}\bf 7.57 \boldsymbol{\times}}$ 50.06 1600
bls12_381_msm_g2, 1000 arguments 621769.22 100801.74 ${\color{green}\bf 7.50 \boldsymbol{\times}}$ 3640.63 31900
bls12_381_mul_projective_g1 486.34 75.01 ${\color{green}\bf 6.48 \boldsymbol{\times}}$ 11.94 45.59
bls12_381_mul_affine_g1 420.01 79.26 ${\color{green}\bf 5.30 \boldsymbol{\times}}$ 11.11 38.74
bls12_381_mul_projective_g2 1498.84 210.50 ${\color{green}\bf 7.12 \boldsymbol{\times}}$ 14.63 146.93
bls12_381_mul_affine_g2 1234.92 214.00 ${\color{green}\bf 5.77 \boldsymbol{\times}}$ 13.17 123.68
bls12_377_pairing 8904.20 1449.52 ${\color{green}\bf 6.14 \boldsymbol{\times}}$ 25.88 1470
bls12_377_msm_g1, 10 arguments 6592.47 902.50 ${\color{green}\bf 7.30 \boldsymbol{\times}}$ 29.20 582.19
bls12_377_msm_g1, 1000 arguments 191793.87 28828.95 ${\color{green}\bf 6.65 \boldsymbol{\times}}$ 1307.62 11000
bls12_377_msm_g2, 10 arguments 22509.51 3251.84 ${\color{green}\bf 6.92 \boldsymbol{\times}}$ 35.06 1860
bls12_377_msm_g2, 1000 arguments 632339.00 94521.78 ${\color{green}\bf 6.69 \boldsymbol{\times}}$ 2556.48 36020
bls12_377_mul_projective_g1 424.21 65.68 ${\color{green}\bf 6.46 \boldsymbol{\times}}$ 11.76 46.54
bls12_377_mul_affine_g1 363.85 65.68 ${\color{green}\bf 5.54 \boldsymbol{\times}}$ 10.50 39.81
bls12_377_mul_projective_g2 1339.39 212.20 ${\color{green}\bf 6.31 \boldsymbol{\times}}$ 14.56 167.91
bls12_377_mul_affine_g2 1122.08 208.74 ${\color{green}\bf 5.38 \boldsymbol{\times}}$ 13.08 141.49
bw6_761_pairing 52065.18 6791.27 ${\color{green}\bf 7.67 \boldsymbol{\times}}$ 34.70 6780
bw6_761_msm_g1, 10 arguments 47050.21 5559.53 ${\color{green}\bf 8.46 \boldsymbol{\times}}$ 67.79 2760
bw6_761_msm_g1, 1000 arguments 1167536.06 143517.21 ${\color{green}\bf 8.14 \boldsymbol{\times}}$ 4630.95 56680
bw6_761_msm_g2, 10 arguments 41055.89 4874.46 ${\color{green}\bf 8.42 \boldsymbol{\times}}$ 58.37 2960
bw6_761_msm_g2, 1000 arguments 1209593.25 143437.77 ${\color{green}\bf 8.43 \boldsymbol{\times}}$ 4345.36 74550
bw6_761_mul_projective_g1 1678.86 223.57 ${\color{green}\bf 7.51 \boldsymbol{\times}}$ 27.54 221.73
bw6_761_mul_affine_g1 1387.87 222.05 ${\color{green}\bf 6.25 \boldsymbol{\times}}$ 27.55 183.16
bw6_761_mul_projective_g2 1919.98 308.60 ${\color{green}\bf 6.22 \boldsymbol{\times}}$ 26.99 221.75
bw6_761_mul_affine_g2 1388.21 222.47 ${\color{green}\bf 6.24 \boldsymbol{\times}}$ 21.90 184.79
ed_on_bls12_381_bandersnatch_msm_sw, 10 arguments 3616.81 557.96 ${\color{green}\bf 6.48 \boldsymbol{\times}}$ 21.43 457.93
ed_on_bls12_381_bandersnatch_msm_sw, 1000 arguments 94473.54 16254.32 ${\color{green}\bf 5.81 \boldsymbol{\times}}$ 982.29 7460
ed_on_bls12_381_bandersnatch_mul_projective_sw 235.38 40.70 ${\color{green}\bf 5.78 \boldsymbol{\times}}$ 9.03 33.12
ed_on_bls12_381_bandersnatch_mul_affine_sw 204.04 41.66 ${\color{green}\bf 4.90 \boldsymbol{\times}}$ 8.78 29.50
ed_on_bls12_381_bandersnatch_msm_te, 10 arguments 5427.77 744.74 ${\color{green}\bf 7.29 \boldsymbol{\times}}$ 24.05 538.16
ed_on_bls12_381_bandersnatch_msm_te, 1000 arguments 106610.20 16690.71 ${\color{green}\bf 6.39 \boldsymbol{\times}}$ 1195.35 7460
ed_on_bls12_381_bandersnatch_mul_projective_te 183.29 34.63 ${\color{green}\bf 5.29 \boldsymbol{\times}}$ 9.55 24.83
ed_on_bls12_381_bandersnatch_mul_affine_te 181.84 33.99 ${\color{green}\bf 5.35 \boldsymbol{\times}}$ 9.50 29.47
ed_on_bls12_377_msm, 10 arguments 5304.03 700.51 ${\color{green}\bf 7.57 \boldsymbol{\times}}$ 24.02 523.27
ed_on_bls12_377_msm, 1000 arguments 105563.53 15757.62 ${\color{green}\bf 6.70 \boldsymbol{\times}}$ 1200.45 7370
ed_on_bls12_377_mul_projective 179.54 32.72 ${\color{green}\bf 5.49 \boldsymbol{\times}}$ 9.72 24.07
ed_on_bls12_377_mul_affine 177.53 33.24 ${\color{green}\bf 5.34 \boldsymbol{\times}}$ 9.76 23.90

[^1]: implemented in a Substrate pallet with arkworks library by this repo: https://github.com/achimcc/substrate-arkworks-examples [^2]: implemented in a Substrate pallet with ark-substrate library, executed through host-function call, computed by this repo: https://github.com/achimcc/substrate-arkworks-examples [^3]: speedup by using ark-substrate and host calls, compared to native speed [^4]: These extrinsics just receive the arguemnts, deserialize them without using them and then take a generator or zero element of the expected return group, serizlize it and return it. Calling a host call through a extrinsic which does nothing has been benchmarked with 3.98µs. Implementation in: https://github.com/achimcc/substrate-arkworks-examples/tree/dummy-calls [^5]: native execution, computed by this repo: https://github.com/achimcc/native-bench-arkworks

Usage

For end user implementation/usage of arkworks curves, we provide an extra library: sp-curves, which is build on top of this library. If you plan to use Arkworks elliptic curves in a Substrate pallet, then check out this repo, we also provide an explanation there for this choice of architecture.

The purpose of this lirary is that it is decoupled from Substrate itself, so that Substrate can consume it, e.g. for Sassafrass consensus. To implement the elliptic curves in Substrate you need to pass the host function calls from the Substrate sp-io crate to the instantiated elliptic curves.

See the substrate-arkworks-examples repo for further implementation details, benchmarks and an example on how to verify a groth16 proof in a Substrate pallet.

BLS12_377

Curve instantiation:

use sp_ark_bls12_377::{Bls12_377 as Bls12_377_Host}

pub struct Host {}

impl HostFunctions for Host {
    fn bls12_377_multi_miller_loop(a: Vec<u8>, b: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_377_multi_miller_loop(a, b)
    }
    fn bls12_377_final_exponentiation(f12: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_377_final_exponentiation(f12)
    }
    fn bls12_377_msm_g1(bases: Vec<u8>, bigints: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_377_msm_g1(bases, bigints)
    }
    fn bls12_377_msm_g2(bases: Vec<u8>, bigints: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_377_msm_g2(bases, bigints)
    }
    fn bls12_377_mul_projective_g1(base: Vec<u8>, scalar: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_377_mul_projective_g1(base, scalar)
    }
    fn bls12_377_mul_projective_g2(base: Vec<u8>, scalar: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_377_mul_projective_g2(base, scalar)
    }
}

type Bls12_377 = Bls12_377_Host<Host>;

BLS12_381

Curve instantiation:

use sp_ark_bls12_381::{Bls12_381 as Bls12_381_Host};

pub struct Host;

pub struct Host {}

impl HostFunctions for Host {
    fn bls12_381_multi_miller_loop(a: Vec<u8>, b: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_381_multi_miller_loop(a, b)
    }
    fn bls12_381_final_exponentiation(f12: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_381_final_exponentiation(f12)
    }
    fn bls12_381_msm_g1(bases: Vec<u8>, bigints: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_381_msm_g1(bases, bigints)
    }
    fn bls12_381_msm_g2(bases: Vec<u8>, bigints: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_381_msm_g2(bases, bigints)
    }
    fn bls12_381_mul_projective_g1(base: Vec<u8>, scalar: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_381_mul_projective_g1(base, scalar)
    }
    fn bls12_381_mul_projective_g2(base: Vec<u8>, scalar: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bls12_381_mul_projective_g2(base, scalar)
    }
}

type Bls12_381 = Bls12_381_Host<Host>;

BW6_761

Curve instantiation:

use sp_ark_bw6_761::{BW6_761 as BW6_761_Host}

pub struct Host;

impl HostFunctions for Host {
    fn bw6_761_multi_miller_loop(a: Vec<u8>, b: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bw6_761_multi_miller_loop(a, b)
    }
    fn bw6_761_final_exponentiation(f12: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bw6_761_final_exponentiation(f12)
    }
    fn bw6_761_msm_g1(bases: Vec<u8>, bigints: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bw6_761_msm_g1(bases, bigints)
    }
    fn bw6_761_msm_g2(bases: Vec<u8>, bigints: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bw6_761_msm_g2(bases, bigints)
    }
    fn bw6_761_mul_projective_g1(base: Vec<u8>, scalar: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bw6_761_mul_projective_g1(base, scalar)
    }
    fn bw6_761_mul_projective_g2(base: Vec<u8>, scalar: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::bw6_761_mul_projective_g2(base, scalar)
    }
}

type BW6_761 = BW6_761_Host<Host>;

ED_ON_BLS12_377

Curve instatiation:

use sp_ark_ed_on_bls12_377::{EdwardsProjective as EdwardsProjective_Host}

pub struct Host;

impl HostFunctions for Host {
    fn ed_on_bls12_377_msm(bases: Vec<u8>, scalars: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::ed_on_bls12_377_msm(bases, scalars)
    }
    fn ed_on_bls12_377_mul_projective(base: Vec<u8>, scalar: Vec<u8>) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::ed_on_bls12_377_mul_projective(base, scalar)
    }
}

type EdwardsProjective = EdwardsProjective_Host<Host>;

ED_ON_BLS12_381_BANDERSNATCH

Curve instantiation:

us sp_ark_ed_on_bls12_381_bandersnatch_bandersnatch::{SWProjective as SWProjective_Host, EdwardsProjective as EdwardsProjective_Host}

pub struct Host;

impl HostFunctions for Host {
    fn ed_on_bls12_381_bandersnatch_bandersnatch_te_msm(
        bases: Vec<u8>,
        scalars: Vec<u8>,
    ) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::ed_on_bls12_381_bandersnatch_bandersnatch_te_msm(bases, scalars)
    }
    fn ed_on_bls12_381_bandersnatch_bandersnatch_sw_msm(
        bases: Vec<u8>,
        scalars: Vec<u8>,
    ) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::ed_on_bls12_381_bandersnatch_bandersnatch_sw_msm(bases, scalars)
    }
    fn ed_on_bls12_381_bandersnatch_bandersnatch_te_mul_projective(
        base: Vec<u8>,
        scalar: Vec<u8>,
    ) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::ed_on_bls12_381_bandersnatch_bandersnatch_te_mul_projective(base, scalar)
    }
    fn ed_on_bls12_381_bandersnatch_bandersnatch_sw_mul_projective(
        base: Vec<u8>,
        scalar: Vec<u8>,
    ) -> Result<Vec<u8>, ()> {
        sp_crypto_ec_utils::elliptic_curves::ed_on_bls12_381_bandersnatch_bandersnatch_sw_mul_projective(base, scalar)
    }
}

type EdwardsProjetive = EdwardsProjective_Host<Host>;
type SWProjective = SWProjective_host<Host>;

Dependencies

~5MB
~102K SLoC