lib.rs
1 // Copyright (c) 2025-2026 ACDC Network 2 // This file is part of the alphavm library. 3 // 4 // Alpha Chain | Delta Chain Protocol 5 // International Monetary Graphite. 6 // 7 // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com). 8 // They built world-class ZK infrastructure. We installed the EASY button. 9 // Their cryptography: elegant. Our modifications: bureaucracy-compatible. 10 // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours. 11 // 12 // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0 13 // All modifications and new work: CC0 1.0 Universal Public Domain Dedication. 14 // No rights reserved. No permission required. No warranty. No refunds. 15 // 16 // https://creativecommons.org/publicdomain/zero/1.0/ 17 // SPDX-License-Identifier: CC0-1.0 18 19 #[allow(unused_imports)] 20 use blst::*; 21 22 use core::ffi::c_void; 23 sppark::cuda_error!(); 24 25 #[repr(C)] 26 pub enum NTTInputOutputOrder { 27 NN = 0, 28 NR = 1, 29 RN = 2, 30 RR = 3, 31 } 32 33 #[repr(C)] 34 pub enum NTTDirection { 35 Forward = 0, 36 Inverse = 1, 37 } 38 39 #[repr(C)] 40 pub enum NTTType { 41 Standard = 0, 42 Coset = 1, 43 } 44 45 extern "C" { 46 fn alphavm_ntt( 47 inout: *mut core::ffi::c_void, 48 lg_domain_size: u32, 49 ntt_order: NTTInputOutputOrder, 50 ntt_direction: NTTDirection, 51 ntt_type: NTTType, 52 ) -> cuda::Error; 53 54 fn alphavm_polymul( 55 out: *mut core::ffi::c_void, 56 pcount: usize, 57 polynomials: *const core::ffi::c_void, 58 plens: *const core::ffi::c_void, 59 ecount: usize, 60 evaluations: *const core::ffi::c_void, 61 elens: *const core::ffi::c_void, 62 lg_domain_size: u32, 63 ) -> cuda::Error; 64 65 fn alphavm_msm( 66 out: *mut c_void, 67 points_with_infinity: *const c_void, 68 npoints: usize, 69 scalars: *const c_void, 70 ffi_affine_sz: usize, 71 ) -> cuda::Error; 72 } 73 74 /////////////////////////////////////////////////////////////////////////////// 75 // Rust functions 76 /////////////////////////////////////////////////////////////////////////////// 77 78 /// Compute an in-place NTT on the input data. 79 #[allow(non_snake_case)] 80 pub fn NTT<T>( 81 domain_size: usize, 82 inout: &mut [T], 83 ntt_order: NTTInputOutputOrder, 84 ntt_direction: NTTDirection, 85 ntt_type: NTTType, 86 ) -> Result<(), cuda::Error> { 87 if (domain_size & (domain_size - 1)) != 0 { 88 panic!("domain_size is not power of 2"); 89 } 90 let lg_domain_size = domain_size.trailing_zeros(); 91 92 let err = unsafe { 93 alphavm_ntt(inout.as_mut_ptr() as *mut core::ffi::c_void, lg_domain_size, ntt_order, ntt_direction, ntt_type) 94 }; 95 96 if err.code != 0 { 97 return Err(err); 98 } 99 Ok(()) 100 } 101 102 /// Compute a polynomial multiply 103 pub fn polymul<T: std::clone::Clone>( 104 domain: usize, 105 polynomials: &Vec<Vec<T>>, 106 evaluations: &Vec<Vec<T>>, 107 zero: &T, 108 ) -> Result<Vec<T>, cuda::Error> { 109 let initial_domain_size = domain; 110 if (initial_domain_size & (initial_domain_size - 1)) != 0 { 111 panic!("domain_size is not power of 2"); 112 } 113 114 let lg_domain_size = initial_domain_size.trailing_zeros(); 115 116 let mut pptrs = Vec::new(); 117 let mut plens = Vec::new(); 118 for polynomial in polynomials { 119 pptrs.push(polynomial.as_ptr() as *const core::ffi::c_void); 120 plens.push(polynomial.len()); 121 } 122 let mut eptrs = Vec::new(); 123 let mut elens = Vec::new(); 124 for evaluation in evaluations { 125 eptrs.push(evaluation.as_ptr() as *const core::ffi::c_void); 126 elens.push(evaluation.len()); 127 } 128 129 let mut out = Vec::new(); 130 out.resize(initial_domain_size, zero.clone()); 131 let err = unsafe { 132 alphavm_polymul( 133 out.as_mut_ptr() as *mut core::ffi::c_void, 134 pptrs.len(), 135 pptrs.as_ptr() as *const core::ffi::c_void, 136 plens.as_ptr() as *const core::ffi::c_void, 137 eptrs.len(), 138 eptrs.as_ptr() as *const core::ffi::c_void, 139 elens.as_ptr() as *const core::ffi::c_void, 140 lg_domain_size, 141 ) 142 }; 143 144 if err.code != 0 { 145 return Err(err); 146 } 147 Ok(out) 148 } 149 150 /// Compute a multi-scalar multiplication 151 pub fn msm<Affine, Projective, Scalar>(points: &[Affine], scalars: &[Scalar]) -> Result<Projective, cuda::Error> { 152 let npoints = scalars.len(); 153 if npoints > points.len() { 154 panic!("length mismatch {} points < {} scalars", npoints, scalars.len()) 155 } 156 #[allow(clippy::uninit_assumed_init)] 157 let mut ret: Projective = unsafe { std::mem::MaybeUninit::uninit().assume_init() }; 158 let err = unsafe { 159 alphavm_msm( 160 &mut ret as *mut _ as *mut c_void, 161 points as *const _ as *const c_void, 162 npoints, 163 scalars as *const _ as *const c_void, 164 std::mem::size_of::<Affine>(), 165 ) 166 }; 167 if err.code != 0 { 168 return Err(err); 169 } 170 Ok(ret) 171 }