{"id":19358377,"url":"https://github.com/paritytech/arkworks-extensions","last_synced_at":"2025-12-12T15:17:43.528Z","repository":{"id":65544522,"uuid":"575910880","full_name":"paritytech/arkworks-extensions","owner":"paritytech","description":"Arkworks extensions enabling customizable hooks for EC operations","archived":false,"fork":false,"pushed_at":"2025-03-14T10:58:11.000Z","size":123617,"stargazers_count":50,"open_issues_count":0,"forks_count":4,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-05-08T00:12:57.457Z","etag":null,"topics":["arkworks","cryptography","elliptic-curves"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paritytech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-08T15:20:18.000Z","updated_at":"2025-04-04T04:33:24.000Z","dependencies_parsed_at":"2023-10-15T09:43:19.358Z","dependency_job_id":"a002d3b1-5f09-4f67-85a4-79f255623a9e","html_url":"https://github.com/paritytech/arkworks-extensions","commit_stats":{"total_commits":566,"total_committers":4,"mean_commits":141.5,"dds":0.09187279151943462,"last_synced_commit":"1b26337a6c3e91ba2494c67d6c20b6dabe9df9f3"},"previous_names":["paritytech/arkworks-extensions","paritytech/ark-substrate"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Farkworks-extensions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Farkworks-extensions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Farkworks-extensions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Farkworks-extensions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paritytech","download_url":"https://codeload.github.com/paritytech/arkworks-extensions/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253675069,"owners_count":21945892,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arkworks","cryptography","elliptic-curves"],"created_at":"2024-11-10T07:11:28.412Z","updated_at":"2025-12-12T15:17:43.476Z","avatar_url":"https://github.com/paritytech.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Arkworks Extensions\n\n## Overview\n\nThis library extends [arkworks-rs/algebra](https://github.com/arkworks-rs/algebra).\n\nWe fork the popular elliptic curves `BLS12_381`, `BLS12_377`, `BW6_761`,\n`ED_ON_BLS12_381_BANDERSNATCH`, `Pallas`, `Vesta`, `SECP256K1` and `ED_ON_BLS12_377` in a way which allows\ndelegating some of the most computationally expensive operations to some user\ndefined hooks.\n\nWe also provide forks of the models `BW6` and `BLS12` to avoid the point\npreparation before the hooks calls during pairing operations. Therefore, we\nredefine the elliptic curve sub-groups `G2` for both models as thin wrappers\naround the affine points and move the point preparation procedure to the\nuser defined hook.\n\n## Usage\n\nThe following usage example is extracted from the hooks provided by\n[substrate-curves](https://github.com/paritytech/substrate-curves) project.\n\nThe project provides a set of ready to use `CurveHooks` implementations compatible with\n[Substrate](https://github.com/paritytech/polkadot-sdk/primitives/crypto/ec-utils)\nhost functions to jump from *wasm32* computational domain into the native host.\n\nThe motivation is:\n- native target is typically more efficient that *wasm32*.\n- *wasm32* is single thread while in the native target we can hopefully leverage\n  the Arkworks `parallel` feature.\n\nNote that Substrate elliptic curves host functions take and return raw byte arrays\nrepresenting SCALE encoded values.\n\n### BLS12-377\n\n```rust\nuse ark_bls12_377_ext::CurveHooks;\nuse ark_ec::{pairing::Pairing, CurveConfig}\nuse ark_scale::{\n    ark_serialize::{Compress, Validate},\n    scale::{Decode, Encode},\n};\nuse sp_crypto_ec_utils::bls12_377_ops;\n\n\nconst SCALE_USAGE: u8 = ark_scale::make_usage(Compress::No, Validate::No);\ntype ArkScale\u003cT\u003e = ark_scale::ArkScale\u003cT, SCALE_USAGE\u003e;o\ntype ArkScaleProjective\u003cT\u003e = ark_scale::hazmat::ArkScaleProjective\u003cT\u003e;\n\n#[derive(Copy, Clone)]\npub struct HostHooks;\n\ntype Bls12_377 = ark_bls12_377_ext::Bls12_377\u003cHostHooks\u003e;\ntype G1Affine = ark_bls12_377_ext::g1::G1Affine\u003cHostHooks\u003e;\ntype G1Config = ark_bls12_377_ext::g1::Config\u003cHostHooks\u003e;\ntype G2Affine = ark_bls12_377_ext::g2::G2Affine\u003cHostHooks\u003e;\ntype G2Config = ark_bls12_377_ext::g2::Config\u003cHostHooks\u003e;\n\n\nimpl CurveHooks for HostHooks {\n    fn bls12_377_multi_miller_loop(\n        g1: impl Iterator\u003cItem = \u003cBls12_377 as Pairing\u003e::G1Prepared\u003e,\n        g2: impl Iterator\u003cItem = \u003cBls12_377 as Pairing\u003e::G2Prepared\u003e,\n    ) -\u003e Result\u003c\u003cBls12_377 as Pairing\u003e::TargetField, ()\u003e {\n        // Encode to SCALE to call into Substrate HF\n        let g1 = ArkScale::from(g1.collect::\u003cVec\u003c_\u003e\u003e()).encode();\n        let g2 = ArkScale::from(g2.collect::\u003cVec\u003c_\u003e\u003e()).encode();\n        // Call into native host function\n        let res = bls12_377_ops::bls12_377_multi_miller_loop(g1, g2).unwrap_or_default();\n        // Decode from SCALE\n        let res = ArkScale::\u003c\u003cBls12_377 as Pairing\u003e::TargetField\u003e::decode(\u0026mut res.as_slice());\n        res.map(|v| v.0).map_err(|_| ())\n    }\n\n    fn bls12_377_final_exponentiation(\n        target: \u003cBls12_377 as Pairing\u003e::TargetField,\n    ) -\u003e Result\u003c\u003cBls12_377 as Pairing\u003e::TargetField, ()\u003e {\n        let target = ArkScale::from(target).encode();\n        let res = bls12_377_ops::bls12_377_final_exponentiation(target).unwrap_or_default();\n        let res = ArkScale::\u003c\u003cBls12_377 as Pairing\u003e::TargetField\u003e::decode(\u0026mut res.as_slice());\n        res.map(|v| v.0).map_err(|_| ())\n    }\n\n    fn bls12_377_msm_g1(\n        bases: \u0026[G1Affine],\n        scalars: \u0026[\u003cG1Config as CurveConfig\u003e::ScalarField],\n    ) -\u003e Result\u003cG1Projective, ()\u003e {\n        let bases = ArkScale::from(bases).encode();\n        let scalars = ArkScale::from(scalars).encode();\n        let res = bls12_377_ops::bls12_377_msm_g1(bases, scalars).unwrap_or_default();\n        let res = ArkScaleProjective::\u003cG1Projective\u003e::decode(\u0026mut res.as_slice());\n        res.map(|v| v.0).map_err(|_| ())\n    }\n\n    fn bls12_377_msm_g2(\n        bases: \u0026[G2Affine],\n        scalars: \u0026[\u003cG2Config as CurveConfig\u003e::ScalarField],\n    ) -\u003e Result\u003cG2Projective, ()\u003e {\n        let bases = ArkScale::from(bases).encode();\n        let scalars = ArkScale::from(scalars).encode();\n        let res = bls12_377_ops::bls12_377_msm_g2(bases, scalars).unwrap_or_default();\n        let res = ArkScaleProjective::\u003cG2Projective\u003e::decode(\u0026mut res.as_slice());\n        res.map(|v| v.0).map_err(|_| ())\n    }\n\n    fn bls12_377_mul_projective_g1(\n        base: \u0026G1Projective,\n        scalar: \u0026[u64],\n    ) -\u003e Result\u003cG1Projective, ()\u003e {\n        let base = ArkScaleProjective::from(base).encode();\n        let scalar = ArkScale::from(scalar).encode();\n        let res = bls12_377_ops::bls12_377_mul_projective_g1(base, scalar).unwrap_or_default();\n        let res = ArkScaleProjective::\u003cG1Projective\u003e::decode(\u0026mut res.as_slice());\n        res.map(|v| v.0).map_err(|_| ())\n    }\n\n    fn bls12_377_mul_projective_g2(\n        base: \u0026G2Projective,\n        scalar: \u0026[u64],\n    ) -\u003e Result\u003cG2Projective, ()\u003e {\n        let base = ArkScaleProjective::from(base).encode();\n        let scalar = ArkScale::from(scalar).encode();\n        let res = bls12_377_ops::bls12_377_mul_projective_g2(base, scalar).unwrap_or_default();\n        let res = ArkScaleProjective::\u003cG2Projective\u003e::decode(\u0026mut res.as_slice());\n        res.map(|v| v.0).map_err(|_| ())\n    }o\n}\n```\n\nFor more working examples refer to [Ark Substrate](https://github.com/davxy/ark-substrate-examples).\n\n\n## ⚠️ Known Limitations ⚠️\n\nBe aware that, while in the hook context, any usage of functions which may\nre-enter into the same hook with the same value, may cause an infinite loop.\n\nWe are aware of hooks re-entrancy issues when using **point checked\ndeserialization** in projective multiplication hooks.\n\nIn particular, if you serialize and deserialize (**with point checking**) the\ninput point in one of the projective multiplication hooks then we end up\nre-entering the multiplication hook with the same value as a consequence of the\ninternally performed check.\n\nThe following invocation flow applies:\n\n1. [Validation of deserialized value](https://github.com/arkworks-rs/algebra/blob/c0666a81190dbcade1b735ffd383a5f577dd33d5/ec/src/models/twisted_edwards/mod.rs#L145-L147).\n2. [Check if point is in the correct subgroup](https://github.com/arkworks-rs/algebra/blob/c0666a81190dbcade1b735ffd383a5f577dd33d5/ec/src/models/twisted_edwards/affine.rs#L321).\n3. [Jump into the `TECurveConfig` for the check](https://github.com/arkworks-rs/algebra/blob/c0666a81190dbcade1b735ffd383a5f577dd33d5/ec/src/models/twisted_edwards/affine.rs#L159).\n4. Calls the \"custom\" (defined by this crate) implementation of `mul_affine` which calls `mul_projective`.\n5. Goto 1\n\nSo pay special attention to the actions in your `CurveHooks` implementations.\n\nIf you encounter any other way to trigger the open, please file an issue.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparitytech%2Farkworks-extensions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparitytech%2Farkworks-extensions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparitytech%2Farkworks-extensions/lists"}