Skip to content

Commit

Permalink
Bigint impl for refactored metal EC backend (#21)
Browse files Browse the repository at this point in the history
* feat: import mont_mul backend from https://github.com/geometryxyz/msl-secp256k1

* chore: add refactored metal_msm, will remove the previous one once this is completed

* chore: migrate prev utils mod to refactored metal msm

* feat: conversion between bigint and arbitrary limb size

* lint

* chore: ignore all metal ir and lib

* test(bigint): add host test

* test(bigint): adapt from https://github.com/geometryxyz/msl-secp256k1

* chore: ignore all constants file since it's been automatically generated

* refactor: add overflow detection and correct suitable bigint val for each cases
  • Loading branch information
moven0831 authored Dec 21, 2024
1 parent a553c49 commit bf1636b
Show file tree
Hide file tree
Showing 39 changed files with 2,702 additions and 1 deletion.
175 changes: 175 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion mopro-msm/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,11 @@ Cargo.lock
src/middleware/gpu_explorations/utils/vectors

# GPU exploration - proptest generated files
proptest-regressions
proptest-regressions

# Metal shader intermediate files and libraries
src/msm/metal_msm/shader/**/*.ir
src/msm/metal_msm/shader/**/*.lib

# Metal shader constants file
src/msm/metal_msm/shader/**/constants.metal
3 changes: 3 additions & 0 deletions mopro-msm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ serde_derive = "1.0"
wasmer = { git = "https://github.com/oskarth/wasmer.git", rev = "09c7070" }
witness = { git = "https://github.com/philsippl/circom-witness-rs.git" }

[dev-dependencies]
serial_test = "3.0.0"

# [dependencies.rayon]
# version = "1"
# optional=false
71 changes: 71 additions & 0 deletions mopro-msm/src/msm/metal/abstraction/limbs_conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ use crate::msm::metal::abstraction::mont_reduction;
// implement to_u32_limbs and from_u32_limbs for BigInt<4>
pub trait ToLimbs {
fn to_u32_limbs(&self) -> Vec<u32>;
fn to_limbs(&self, num_limbs: usize, log_limb_size: u32) -> Vec<u32>;
}

pub trait FromLimbs {
fn from_u32_limbs(limbs: &[u32]) -> Self;
fn from_limbs(limbs: &[u32], log_limb_size: u32) -> Self;
fn from_u128(num: u128) -> Self;
fn from_u32(num: u32) -> Self;
}
Expand All @@ -26,6 +28,37 @@ impl ToLimbs for BigInteger256 {
});
limbs
}

fn to_limbs(&self, num_limbs: usize, log_limb_size: u32) -> Vec<u32> {
let mut result = vec![0u32; num_limbs];
let limb_size = 1u32 << log_limb_size;
let mask = limb_size - 1;

// Convert to little-endian representation
let bytes = self.to_bytes_le();
let mut val = 0u32;
let mut bits = 0u32;
let mut limb_idx = 0;

for &byte in bytes.iter() {
val |= (byte as u32) << bits;
bits += 8;

while bits >= log_limb_size && limb_idx < num_limbs {
result[limb_idx] = val & mask;
val >>= log_limb_size;
bits -= log_limb_size;
limb_idx += 1;
}
}

// Handle any remaining bits
if bits > 0 && limb_idx < num_limbs {
result[limb_idx] = val;
}

result
}
}

// convert from little endian to big endian
Expand All @@ -40,6 +73,10 @@ impl ToLimbs for Fq {
});
limbs
}

fn to_limbs(&self, num_limbs: usize, log_limb_size: u32) -> Vec<u32> {
self.0.to_limbs(num_limbs, log_limb_size)
}
}

impl FromLimbs for BigInteger256 {
Expand All @@ -63,6 +100,35 @@ impl FromLimbs for BigInteger256 {
fn from_u32(num: u32) -> Self {
BigInteger256::new([num as u64, 0, 0, 0])
}

fn from_limbs(limbs: &[u32], log_limb_size: u32) -> Self {
let mut result = [0u64; 4];
let limb_size = log_limb_size as usize;
let mut accumulated_bits = 0;
let mut current_u64 = 0u64;
let mut result_idx = 0;

for &limb in limbs {
// Add the current limb at the appropriate position
current_u64 |= (limb as u64) << accumulated_bits;
accumulated_bits += limb_size;

// If we've accumulated 64 bits or more, store the result
while accumulated_bits >= 64 && result_idx < 4 {
result[result_idx] = current_u64;
current_u64 = limb as u64 >> (limb_size - (accumulated_bits - 64));
accumulated_bits -= 64;
result_idx += 1;
}
}

// Handle any remaining bits
if accumulated_bits > 0 && result_idx < 4 {
result[result_idx] = current_u64;
}

BigInteger256::new(result)
}
}

impl FromLimbs for Fq {
Expand All @@ -88,4 +154,9 @@ impl FromLimbs for Fq {
num as u64, 0, 0, 0,
])))
}

fn from_limbs(limbs: &[u32], log_limb_size: u32) -> Self {
let bigint = BigInteger256::from_limbs(limbs, log_limb_size);
Fq::new(mont_reduction::raw_reduction(bigint))
}
}
19 changes: 19 additions & 0 deletions mopro-msm/src/msm/metal_msm/host/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use thiserror::Error;

#[derive(Debug, Error)]
pub enum MetalError {
#[error("Couldn't find a system default device for Metal")]
DeviceNotFound(),
#[error("Couldn't create a new Metal library: {0}")]
LibraryError(String),
#[error("Couldn't create a new Metal function object: {0}")]
FunctionError(String),
#[error("Couldn't create a new Metal compute pipeline: {0}")]
PipelineError(String),
#[error("Could not calculate {1} root of unity")]
RootOfUnityError(String, u64),
// #[error("Input length is {0}, which is not a power of two")]
// InputError(usize),
#[error("Invalid input: {0}")]
InputError(String),
}
Loading

0 comments on commit bf1636b

Please sign in to comment.