lib.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. mod utils;
  2. use wasm_bindgen::prelude::*;
  3. use spiral_rs::{params::*, util::*, client::*, discrete_gaussian::*};
  4. const UUID_V4_LEN: usize = 36;
  5. // console_log! macro
  6. #[wasm_bindgen]
  7. extern "C" {
  8. #[wasm_bindgen(js_namespace = console)]
  9. fn log(s: &str);
  10. }
  11. macro_rules! console_log {
  12. ($($t:tt)*) => (log(&format_args!($($t)*).to_string()))
  13. }
  14. // Container class for a static lifetime Client
  15. // Avoids a lifetime in the return signature of bound Rust functions
  16. #[wasm_bindgen]
  17. pub struct WrappedClient {
  18. client: Client<'static>
  19. }
  20. // Unsafe global with a static lifetime
  21. // Accessed unsafely only once, at load / setup
  22. static mut PARAMS: Params = get_empty_params();
  23. // Very simply test to ensure random generation is not obviously biased.
  24. fn dg_seems_okay() {
  25. let params = get_test_params();
  26. let mut dg = DiscreteGaussian::init(&params);
  27. let mut v = Vec::new();
  28. let trials = 10000;
  29. let mut sum = 0;
  30. for _ in 0..trials {
  31. let val = dg.sample();
  32. v.push(val);
  33. sum += val;
  34. }
  35. let mean = sum as f64 / trials as f64;
  36. let std_dev = params.noise_width / f64::sqrt(2f64 * std::f64::consts::PI);
  37. let std_dev_of_mean = std_dev / f64::sqrt(trials as f64);
  38. assert!(f64::abs(mean) < std_dev_of_mean * 5f64);
  39. }
  40. // Initializes a client; can optionally take in a set of parameters
  41. #[wasm_bindgen]
  42. pub fn initialize(json_params: Option<String>) -> WrappedClient {
  43. dg_seems_okay();
  44. // spiral_rs::ntt::test::ntt_correct();
  45. let cfg = r#"
  46. {'kinda_direct_upload': 1,
  47. 'n': 5,
  48. 'nu_1': 11,
  49. 'nu_2': 3,
  50. 'p': 65536,
  51. 'q_prime_bits': 27,
  52. 's_e': 57.793748020122216,
  53. 't_GSW': 3,
  54. 't_conv': 56,
  55. 't_exp': 56,
  56. 't_exp_right': 56}
  57. "#;
  58. let mut cfg = cfg.replace("'", "\"");
  59. if json_params.is_some() {
  60. cfg = json_params.unwrap();
  61. }
  62. let client;
  63. // this minimal unsafe operation is need to initialize state
  64. unsafe {
  65. PARAMS = params_from_json(&cfg);
  66. client = Client::init(&PARAMS);
  67. }
  68. WrappedClient { client }
  69. }
  70. #[wasm_bindgen]
  71. pub fn generate_public_parameters(c: &mut WrappedClient) -> Box<[u8]> {
  72. c.client.generate_keys().serialize().into_boxed_slice()
  73. }
  74. #[wasm_bindgen]
  75. pub fn generate_query(c: &mut WrappedClient, id: &str, idx_target: usize) -> Box<[u8]> {
  76. assert_eq!(id.len(), UUID_V4_LEN);
  77. let query = c.client.generate_query(idx_target);
  78. let mut query_buf = query.serialize();
  79. let mut full_query_buf = id.as_bytes().to_vec();
  80. full_query_buf.append(&mut query_buf);
  81. full_query_buf.into_boxed_slice()
  82. }
  83. #[wasm_bindgen]
  84. pub fn decode_response(c: &mut WrappedClient, data: Box<[u8]>) -> Box<[u8]> {
  85. c.client.decode_response(&*data).into_boxed_slice()
  86. }