#![cfg_attr(not(feature = "emulate"), no_std)]
#![cfg_attr(not(feature = "emulate"), feature(wasm_simd, simd_ffi))]
#[cfg(feature = "emulate")]
pub use std::process::exit;
scale_impl_generator::impls!();
#[cfg(not(feature = "emulate"))]
mod types {
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct ClearModp(pub core::arch::wasm32::v128);
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct SecretModp(f32);
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct SecretI64(f64);
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct SecretBit(pub(crate) SecretModp);
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct RawSecretBit(pub(crate) f64);
}
#[cfg(feature = "emulate")]
mod types {
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct ClearModp(pub(crate) i64);
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct SecretModp(pub(crate) ClearModp);
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct SecretI64(pub(crate) i64);
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct SecretBit(pub(crate) i64);
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct RawSecretBit(pub(crate) i64);
}
pub use types::*;
macro_rules! any_register {
($($bound:path),*) => {
pub trait AnyRegister: $($bound+)* Sized {}
};
}
impl AnyRegister for ClearModp {}
impl AnyRegister for SecretModp {}
impl AnyRegister for i64 {}
impl AnyRegister for SecretI64 {}
use core::ops::*;
any_register! {
Stack,
alloc::GetAllocator,
Add<Output = Self>,
Sub<Output = Self>,
Mul<Output = Self>,
StoreInMem<i64>,
LoadFromMem<i64>
}
pub trait InnerModp:
AnyRegister
+ From<ClearModp>
+ Into<SecretModp>
+ RevealIfSecret
+ Mul<ClearModp, Output = Self>
+ Add<ClearModp, Output = Self>
+ Sub<ClearModp, Output = Self>
+ Mul<SecretModp, Output = SecretModp>
+ Add<SecretModp, Output = SecretModp>
+ Sub<SecretModp, Output = SecretModp>
{
}
impl InnerModp for ClearModp {}
impl InnerModp for SecretModp {}
pub trait Modp<Other: InnerModp>:
InnerModp
+ Mul<Other, Output = SecretModp>
+ Add<Other, Output = SecretModp>
+ Sub<Other, Output = SecretModp>
{
}
impl Modp<ClearModp> for SecretModp {}
impl Modp<SecretModp> for ClearModp {}
impl Modp<SecretModp> for SecretModp {}
pub trait StoreInMem<Index> {
unsafe fn store_in_mem(&self, idx: Index);
}
pub trait LoadFromMem<Index> {
fn load_from_mem(idx: Index) -> Self;
}
impl<T: StoreInMem<i64>> StoreInMem<(i64, i64)> for Option<T> {
unsafe fn store_in_mem(&self, idk: (i64, i64)) {
match self {
None => 0_i64.store_in_mem(idk.0),
Some(a) => {
1_i64.store_in_mem(idk.0);
a.store_in_mem(idk.1);
}
};
}
}
impl<T: LoadFromMem<i64>> LoadFromMem<(i64, i64)> for Option<T> {
fn load_from_mem(idk: (i64, i64)) -> Option<T> {
let ind = i64::load_from_mem(idk.0);
match ind {
1 => Some(T::load_from_mem(idk.1)),
_ => None,
}
}
}
mod stack_address;
#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct StackAddress(i64);
pub trait Stack {
unsafe fn push(val: &Self);
unsafe fn pop() -> Self;
unsafe fn peek(addr: StackAddress) -> Self;
unsafe fn poke(addr: StackAddress, val: &Self);
fn get_stack_pointer() -> StackAddress;
unsafe fn peek_from_top(offset: i64) -> Self;
unsafe fn poke_from_top(offset: i64, val: &Self);
}
use core::mem::MaybeUninit;
impl<T: alloc::GetAllocator + Stack, const N: usize> Stack for [T; N] {
#[inline(always)]
unsafe fn push(array: &Self) {
for val in array.iter() {
T::push(&val);
}
}
#[inline(always)]
unsafe fn pop() -> Self {
let mut array: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();
for i in (0..N).rev() {
array[i] = MaybeUninit::new(T::pop());
}
core::mem::transmute_copy(&array)
}
#[inline(always)]
unsafe fn peek(addr: StackAddress) -> Self {
let mut array: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();
for i in 0..N {
array[i] = MaybeUninit::new(T::peek(addr + i as _));
}
core::mem::transmute_copy(&array)
}
#[inline(always)]
unsafe fn poke(addr: StackAddress, array: &Self) {
for (i, val) in array.iter().enumerate() {
T::poke(addr + i as _, &val);
}
}
#[inline(always)]
unsafe fn peek_from_top(offset: i64) -> Self {
let mut array: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();
for i in 0..N {
array[i] = MaybeUninit::new(T::peek_from_top(offset + i as i64));
}
core::mem::transmute_copy(&array)
}
#[inline(always)]
unsafe fn poke_from_top(offset: i64, array: &Self) {
for (i, val) in array.iter().enumerate() {
T::poke_from_top(offset + i as i64, &val);
}
}
#[inline(always)]
fn get_stack_pointer() -> StackAddress {
panic!("this operation makes no sense")
}
}
pub trait Reveal {
type Output;
fn reveal(&self) -> Self::Output;
}
pub trait RevealIfSecret {
type Output;
fn reveal_if_secret(&self) -> Self::Output;
}
mod clear_modp;
mod i64;
mod io;
mod print;
mod secret_bit;
mod secret_i64;
mod secret_modp;
mod system;
pub use io::*;
pub use print::*;
pub use system::*;
#[cfg(not(feature = "emulate"))]
extern "Rust" {
fn __black_box(i: i64) -> i64;
pub fn reveal(s: SecretModp) -> ClearModp;
fn pop_secret_modp() -> SecretModp;
fn pop_secret_bit() -> RawSecretBit;
fn pop_secret_i64() -> SecretI64;
fn __bit() -> SecretModp;
}
#[inline(always)]
#[cfg(not(feature = "emulate"))]
pub fn __triple() -> (SecretModp, SecretModp, SecretModp) {
extern "C" {
fn __triple();
}
unsafe {
__triple();
(pop_secret_modp(), pop_secret_modp(), pop_secret_modp())
}
}
#[inline(always)]
#[cfg(not(feature = "emulate"))]
pub fn __square() -> (SecretModp, SecretModp) {
extern "C" {
fn __square();
}
unsafe {
__square();
(pop_secret_modp(), pop_secret_modp())
}
}
const TEST_MEMORY_OFFSET: i64 = 0;
#[cfg(feature = "emulate")]
#[inline(never)]
pub fn black_box(i: i64) -> i64 {
i
}
#[cfg(not(feature = "emulate"))]
#[inline(always)]
pub fn black_box(i: i64) -> i64 {
unsafe { __black_box(i) }
}
#[cfg(feature = "emulate")]
#[inline(never)]
pub unsafe fn reveal(s: SecretModp) -> ClearModp {
s.0
}
#[panic_handler]
#[cfg(not(feature = "emulate"))]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
unsafe { __crash() }
}
#[cfg(feature = "emulate")]
mod emulated_impls;
#[cfg(feature = "emulate")]
pub use emulated_impls::__mul2sint;
#[cfg(feature = "emulate")]
use num_bigint::BigInt;
#[cfg(feature = "emulate")]
pub fn __triple() -> (SecretModp, SecretModp, SecretModp) {
let value: BigInt = From::from(1);
let s = SecretModp(value.into());
(s, s, s)
}
#[cfg(feature = "emulate")]
pub fn __square() -> (SecretModp, SecretModp) {
let value: BigInt = From::from(1);
let s = SecretModp(value.into());
(s, s)
}
#[cfg(feature = "emulate")]
pub unsafe fn __bit() -> SecretModp {
let s = SecretModp::from(0);
s
}
pub trait Test {
#[track_caller]
fn test(self);
}
pub trait TestValue {
#[track_caller]
fn test_value(self, val: Self);
}
pub trait TestMem {
#[track_caller]
fn test_mem<const I: u32>(self, t_location: ConstU32<I>);
}
pub trait Output {
fn output<const C: u32>(self, ch: Channel<C>);
}
pub trait Input {
fn input<const C: u32>(ch: Channel<C>) -> Self;
}
#[cfg(not(feature = "emulate"))]
mod testing;
#[cfg(feature = "emulate")]
mod testing_emulated;
pub mod alloc;
pub use scale_impl_generator::main;
#[doc(hidden)]
#[macro_export]
macro_rules! __main {
(KAPPA = $kappa:expr;) => {
use $crate::print;
use $crate::*;
type SecretInteger<const K: u64> = scale_std::integer::SecretInteger<K, $kappa>;
type SecretFixed<const K: u64, const F: u64> =
scale_std::fixed_point::SecretFixed<K, F, $kappa>;
type SecretFloat<const V: u64, const P: u64> =
scale_std::floating_point::SecretFloat<V, P, $kappa, true>;
type ClearFloat<const V: u64, const P: u64> =
scale_std::floating_point::ClearFloat<V,P,true>;
#[cfg(not(test))]
mod helper {
#[no_mangle]
fn main() {
extern "Rust" {
fn init_wasm_heap_memory();
}
unsafe {
init_wasm_heap_memory();
}
super::main();
#[cfg(feature = "emulate")]
$crate::exit(0);
}
}
};
(KAPPA = $kappa:expr; DETECT_OVERFLOW = $detect_overflow:expr) => {
use $crate::print;
use $crate::*;
type SecretInteger<const K: u64> = scale_std::integer::SecretInteger<K, $kappa>;
type SecretFixed<const K: u64, const F: u64> =
scale_std::fixed_point::SecretFixed<K, F, $kappa>;
type SecretFloat<const V: u64, const P: u64> =
scale_std::floating_point::SecretFloat<V, P, $kappa, $detect_overflow>;
type ClearFloat<const V: u64, const P: u64> =
scale_std::floating_point::ClearFloat<V,P,$detect_overflow>
#[cfg(not(test))]
mod helper {
#[no_mangle]
fn main() {
extern "Rust" {
fn init_wasm_heap_memory();
}
unsafe {
init_wasm_heap_memory();
}
super::main();
#[cfg(feature = "emulate")]
$crate::exit(0);
}
}
};
}
#[macro_export]
macro_rules! panic {
($($tt:tt)*) => {{
$crate::print!($($tt)*);
unsafe { $crate::__crash() }
}};
}
#[macro_export]
macro_rules! assert {
($e:expr) => {
if !$e {
$crate::panic!("assertion failed: ", stringify!($e));
}
};
}
pub trait ScaleCmp<Other, A> {
fn lt(self, other: Other) -> A;
fn le(self, other: Other) -> A;
fn gt(self, other: Other) -> A;
fn ge(self, other: Other) -> A;
fn eq(self, other: Other) -> A;
fn ne(self, other: Other) -> A;
}
pub trait ScaleCmpZ<A> {
fn ltz(self) -> A;
fn lez(self) -> A;
fn gtz(self) -> A;
fn gez(self) -> A;
fn eqz(self) -> A;
fn nez(self) -> A;
}
pub trait Rand {
fn rand(self) -> i64;
}
pub trait Randomize {
fn randomize() -> Self;
}
#[macro_export]
macro_rules! execute_garbled_circuit {
($id:ident($($arg:expr),*) -> $($ret:ty),*) => {{
$(Stack::push(&$arg);)*
execute_garbled_circuit(ConstU32::<$id>);
($(<$ret>::pop()),*)
}};
}
#[macro_export]
macro_rules! execute_local_function {
($id:ident($($arg:expr),*) -> $($ret:ty),*) => {{
$(Stack::push(&$arg);)*
execute_local_function(ConstU32::<$id>);
($(<$ret>::pop()),*)
}};
}
#[derive(Copy, Clone)]
pub struct Player<const ID: u32>;
#[derive(Copy, Clone)]
pub struct ConstU32<const U: u32>;
#[derive(Copy, Clone)]
pub struct ConstU64<const U: u64>;
#[derive(Copy, Clone)]
pub struct ConstBool<const U: bool>;
#[derive(Copy, Clone)]
pub struct ConstI32<const I: i32>;
#[derive(Copy, Clone)]
pub struct Channel<const ID: u32>;
trait AssemblyType {
type Type;
fn to_asm(self) -> Self::Type;
}
impl AssemblyType for i64 {
type Type = i64;
#[inline(always)]
fn to_asm(self) -> Self::Type {
self
}
}
impl AssemblyType for ClearModp {
type Type = ClearModp;
#[inline(always)]
fn to_asm(self) -> Self::Type {
self
}
}
impl AssemblyType for SecretModp {
type Type = SecretModp;
#[inline(always)]
fn to_asm(self) -> Self::Type {
self
}
}
impl AssemblyType for SecretBit {
type Type = SecretBit;
#[inline(always)]
fn to_asm(self) -> Self::Type {
self
}
}
impl AssemblyType for SecretI64 {
type Type = SecretI64;
#[inline(always)]
fn to_asm(self) -> Self::Type {
self
}
}
impl<const I: u32> AssemblyType for Channel<I> {
type Type = u32;
#[inline(always)]
fn to_asm(self) -> Self::Type {
I
}
}
impl<const I: i32> AssemblyType for ConstI32<I> {
type Type = i32;
#[inline(always)]
fn to_asm(self) -> Self::Type {
I
}
}
impl<const I: u32> AssemblyType for ConstU32<I> {
type Type = u32;
#[inline(always)]
fn to_asm(self) -> Self::Type {
I
}
}
impl<const I: u64> AssemblyType for ConstU64<I> {
type Type = u64;
#[inline(always)]
fn to_asm(self) -> Self::Type {
I
}
}
impl<const I: bool> AssemblyType for ConstBool<I> {
type Type = bool;
#[inline(always)]
fn to_asm(self) -> Self::Type {
I
}
}
impl<const I: u32> AssemblyType for Player<I> {
type Type = u32;
#[inline(always)]
fn to_asm(self) -> Self::Type {
I
}
}
impl AssemblyType for Never {
type Type = Never;
#[inline(always)]
fn to_asm(self) -> Self::Type {
self
}
}
type Never = <F as HasOutput>::Output;
pub trait HasOutput {
type Output;
}
impl<O> HasOutput for fn() -> O {
type Output = O;
}
type F = fn() -> !;