{"id":31923338,"url":"https://github.com/fuellabs/wgpu-sigops","last_synced_at":"2025-10-13T23:49:36.686Z","repository":{"id":257683806,"uuid":"836548147","full_name":"FuelLabs/wgpu-sigops","owner":"FuelLabs","description":null,"archived":false,"fork":false,"pushed_at":"2024-08-01T17:43:51.000Z","size":351,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":13,"default_branch":"master","last_synced_at":"2025-05-21T18:34:22.617Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/FuelLabs.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":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-08-01T04:50:44.000Z","updated_at":"2024-10-24T14:10:38.000Z","dependencies_parsed_at":"2024-09-18T04:29:36.207Z","dependency_job_id":null,"html_url":"https://github.com/FuelLabs/wgpu-sigops","commit_stats":null,"previous_names":["fuellabs/wgpu-sigops"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/FuelLabs/wgpu-sigops","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FuelLabs%2Fwgpu-sigops","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FuelLabs%2Fwgpu-sigops/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FuelLabs%2Fwgpu-sigops/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FuelLabs%2Fwgpu-sigops/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/FuelLabs","download_url":"https://codeload.github.com/FuelLabs/wgpu-sigops/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/FuelLabs%2Fwgpu-sigops/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279017229,"owners_count":26086016,"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","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2025-10-13T23:49:33.234Z","updated_at":"2025-10-13T23:49:36.680Z","avatar_url":"https://github.com/FuelLabs.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `wgpu_sig_ops`\n\n## Getting started\n\nClone this repository:\n\n```bash\ngit clone git@github.com:geometers/wgpu_sig_ops.git\n```\n\nRun the tests:\n\n```\ncd wgpu_sig_ops \u0026\u0026\ncargo test -- --skip benchmarks\n```\n\n## Usage\n\n### Warmup\n\nNote that the first invocation of any GPU shader will take signficantly longer\nthan subsequent invocations. \n\n| Shader | Linux + Nvidia A1000 (seconds) | Apple M1 Mini (seconds) |\n|-|-|-|\n| secp256k1 ECDSA (single shader)    | 129  | N/A |\n| secp256r1 ECDSA (single shader)    | 125  | N/A |\n| ed25519 EdDSA (single shader)      | 30   | N/A |\n| secp256k1 ECDSA (multiple shaders) | 30   | 2.5 |\n| secp256r1 ECDSA (multiple shaders) | 77   | 2   |\n| ed25519 EdDSA (multiple shaders)   | 28   | 2.8 |\n\n**We recommend using the multi-shader approach** because it enjoys a shorter\ninitial warmup time and has overall better performance compared to the\nsingle-shader approach.\n\n### secp256k1 and secp256r1 ECDSA signature recovery\n\nTo perform multiple secp256k1 / secp256r1 signature recovery operations in\nparallel, use `ecrecover()` in either `src/secp256k1_ecdsa.rs` or\n`src/secp256r1_ecdsa.rs` respectively.\n\nThis function uses the multiple-shader approach. To use the single-shader\napproach, use `ecrecover_single` instead.\n\nThe function signature of `ecrecover` or `ecrecover_single` is:\n\n```rs\npub async fn ecrecover(\n    signatures: Vec\u003cSignature\u003e,\n    messages: Vec\u003cMessage\u003e,\n    table_limbs: \u0026Vec\u003cu32\u003e,\n    log_limb_size: u32,\n) -\u003e Vec\u003cVec\u003cu8\u003e\u003e\n```\n\n`Signature` and `Message` are from\n[`fuel-crypto`](https://crates.io/crates/fuel-crypto).\n\nThe length of `signatures` and `messages` should be the same.\n\n`table_limbs` are precomputed multiples of the secp256k1 or secp256r1 generator\npoint, and can be easily generated using `precompute::secp256k1_bases` or\n`precompute::secp256r1_bases` respectively.\n\n`log_limb_size` indicates the bitwidth of each limb in the shaders'\nrepresentation of big integers. A safe default is 13.\n\nThe output is a `Vec` of byte-vectors which correspond to the big-integer byte\nrepresentation of the affine public key per i-th recovery.\n\n### ed25519 EdDSA signature verification\n\nTo perform multiple ed25519 signature verification operations in\nparallel, use `ecverify()` in `src/ed25519_eddsa.rs`.\n\nThis function uses the multiple-shader approach. To use the single-shader\napproach, use `ecverify_single` instead.\n\nThe function signature of `ecverify` or `ecverify_single` is:\n\n```rs\npub async fn ecverify(\n    signatures: Vec\u003cSignature\u003e,\n    messages: Vec\u003cMessage\u003e,\n    verifying_keys: Vec\u003cVerifyingKey\u003e,\n    table_limbs: \u0026Vec\u003cu32\u003e,\n    log_limb_size: u32,\n) -\u003e Vec\u003cbool\u003e\n```\n\n`Signature` is from [`ed25519-dalek`](https://crates.io/crates/ed25519-dalek).\n`Message` and `VerifyingKey` are from\n[`fuel-crypto`](https://crates.io/crates/fuel-crypto).\n\n`table_limbs` are precomputed multiples of the curve25519 generator\npoint, and can be easily generated using `precompute::ed25519_bases`.\n\nThe output is a `Vec` of booleans which correspond to `true` if the i-th\nrecovery is valid, and `false` otherwise.\n\n### Examples\n\nSee the following source files for examples on how to invoke the GPU shaders:\n\n- `src/benchmarks/secp256k1_ecdsa.rs`\n- `src/benchmarks/secp256r1_ecdsa.rs`\n- `src/benchmarks/ed25519_eddsa.rs`\n\n## Overview\n\nThis repository contains GPU shaders for the following cryptographic operations:\n\n- secp256k1 ECDSA signature recovery\n- secp256r1 ECDSA signature recovery\n- ed25519 EdDSA signature verification\n\nThese shaders are written to mirror the same underlying algorithms and code\nthat Fuel nodes use.\n\nThese GPU shaders are written in the [WebGPU Shader\nLanguage](https://www.w3.org/TR/WGSL/), and are executed by the\n[wgpu](https://github.com/gfx-rs/wgpu) API which works with Rust.\n\nThe constituent algorithms for these operations, which also come with their own\nunit tests, include:\n\n- Big integer addition, subtraction, multiplication, and halving\n- Bytestring-to-big-integer conversion\n- Finite field addition, subtraction, inversion, and multiplication\n- Multiplication of finite field elements in Montgomery form\n- Barrett reduction\n- Square root calculation where the modulus is 3 mod 4\n- Projective curve point addition and doubling\n- Extended Twisted Edwards curve point addition and doubling\n- Shamir-Strauss EC multiplication\n- Double-and-add EC multiplication\n- Fixed-base windowed EC multiplication\n- SHA512\n\nThese tests execute the same operations in CPU and in GPU, and compare the\nresult to ensure correctness. For instance, for the ECDSA tests, the output of\nthe shader is checked against the output of the relevant ECDSA signature\nrecovery function from the\n[`fuel-crypto`](https://crates.io/crates/fuel-crypto) library.\n\nOf particular note is that the ed25519 EdDSA signature verification shader follows the\n[`ed25519-dalek`](https://crates.io/crates/ed25519-dalek) implementation of\nEdDSA. This is important because [not all EdDSA implementations are the\nsame](https://hdevalence.ca/blog/2020-10-04-its-25519am), and nodes must run\nthe same implementation in order to maintain consensus.\n\n## Benchmarks\n\n```\ncargo test --release multiple_benchmarks -- --nocapture\n```\n\n### Results\n\nThe following benchmarks were run on a 13th Gen Intel(R) Core(TM) i7-13700HX\nmachine with an [Nvidia RTX\nA1000](https://www.notebookcheck.net/NVIDIA-RTX-A1000-Laptop-GPU-GPU-Benchmarks-and-Specs.615862.0.html)\ngraphics card (2560 cores), a Macbook Pro (M3), and a M1 Mini. The CPU benchmarks\nwere run with the `--release` flag, and the GPU timings include data transfer\nboth ways.\n\nFor each benchmark, each signature is handled in parallel by the GPU, while the\nCPU handles it serially. The results show that after a certain number of\nsignatures, GPU performance beats CPU.\n\nTo ensure a fair comparision, the CPU benchmarks use the same libraries that\n[`fuel-crypto`](https://crates.io/crates/fuel-crypto) uses under the hood:\n\n- [`secp256k1`](https://crates.io/crates/secp256k1), which uses C bindings to\n  `libsecp256k1`\n- [`p256`](https://crates.io/crates/p256), a pure Rust implementation of the\n  secp256r1 curve\n- [`ed25519-dalek`](https://crates.io/crates/ed25519-dalek), a pure Rust\n  implementation of curve25519 and the ed25519 signature scheme.\n\nThe results may be viewed here: https://hackmd.io/@weijiek/r1u2Ka5OR\n\n### Montgomery multiplication benchmarks\n\nThese benchmarks can help select the best choice of limb size for different platforms.\n\n```bash\ncargo test mont_mul_benchmarks -- --nocapture\n```\n\n## Troubleshooting\n\n### If shaders aren't cached\n\nThe second and subsequent runs of any shader should always be much faster than\nthe first run, because the GPU backend will compile and cache it. In some\ncases, this may not be the case, leading to consistently slow runs for no\napparent reason. To address the issue, consider deleting the shader cache on\nyour system.\n\nOn Linux machines with Nvidia GPUs, the cache may be located at\n`~/.cache/nvidia/GLCache/`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuellabs%2Fwgpu-sigops","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffuellabs%2Fwgpu-sigops","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuellabs%2Fwgpu-sigops/lists"}