fhe.rs 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::time::Instant;
  19. use tfhe::integer::ciphertext::RadixCiphertext;
  20. use tfhe::integer::{ClientKey, ServerKey};
  21. use crate::NUMBER_OF_BLOCKS;
  22. fn vector_sum(server_key: &ServerKey, orders: &mut [RadixCiphertext]) -> RadixCiphertext {
  23. let mut total_volume = server_key.create_trivial_zero_radix(NUMBER_OF_BLOCKS);
  24. for order in orders {
  25. server_key.smart_add_assign(&mut total_volume, order);
  26. }
  27. total_volume
  28. }
  29. fn fill_orders(
  30. server_key: &ServerKey,
  31. orders: &mut [RadixCiphertext],
  32. total_volume: RadixCiphertext,
  33. ) {
  34. let mut volume_left_to_transact = total_volume;
  35. for order in orders {
  36. let mut filled_amount = server_key.smart_min(&mut volume_left_to_transact, order);
  37. server_key.smart_sub_assign(&mut volume_left_to_transact, &mut filled_amount);
  38. *order = filled_amount;
  39. }
  40. }
  41. /// FHE implementation of the volume matching algorithm.
  42. ///
  43. /// Matches the given encrypted [sell_orders] with encrypted [buy_orders] using the given
  44. /// [server_key]. The amount of the orders that are successfully filled is written over the original
  45. /// order count.
  46. pub fn volume_match(
  47. sell_orders: &mut [RadixCiphertext],
  48. buy_orders: &mut [RadixCiphertext],
  49. server_key: &ServerKey,
  50. ) {
  51. println!("Calculating total sell and buy volumes...");
  52. let time = Instant::now();
  53. let mut total_sell_volume = vector_sum(server_key, sell_orders);
  54. let mut total_buy_volume = vector_sum(server_key, buy_orders);
  55. println!(
  56. "Total sell and buy volumes are calculated in {:?}",
  57. time.elapsed()
  58. );
  59. println!("Calculating total volume to be matched...");
  60. let time = Instant::now();
  61. let total_volume = server_key.smart_min(&mut total_sell_volume, &mut total_buy_volume);
  62. println!(
  63. "Calculated total volume to be matched in {:?}",
  64. time.elapsed()
  65. );
  66. println!("Filling orders...");
  67. let time = Instant::now();
  68. fill_orders(server_key, sell_orders, total_volume.clone());
  69. fill_orders(server_key, buy_orders, total_volume);
  70. println!("Filled orders in {:?}", time.elapsed());
  71. }
  72. pub fn tester(
  73. client_key: &ClientKey,
  74. server_key: &ServerKey,
  75. input_sell_orders: &[u16],
  76. input_buy_orders: &[u16],
  77. expected_filled_sells: &[u16],
  78. expected_filled_buys: &[u16],
  79. fhe_function: fn(&mut [RadixCiphertext], &mut [RadixCiphertext], &ServerKey),
  80. ) {
  81. let encrypt = |pt: u16| client_key.encrypt_radix(pt as u64, NUMBER_OF_BLOCKS);
  82. let mut encrypted_sell_orders = input_sell_orders
  83. .iter()
  84. .cloned()
  85. .map(encrypt)
  86. .collect::<Vec<RadixCiphertext>>();
  87. let mut encrypted_buy_orders = input_buy_orders
  88. .iter()
  89. .cloned()
  90. .map(encrypt)
  91. .collect::<Vec<RadixCiphertext>>();
  92. println!("Running FHE implementation...");
  93. let time = Instant::now();
  94. fhe_function(
  95. &mut encrypted_sell_orders,
  96. &mut encrypted_buy_orders,
  97. server_key,
  98. );
  99. println!("Ran FHE implementation in {:?}", time.elapsed());
  100. let decrypt = |ct| client_key.decrypt_radix::<u64>(ct) as u16;
  101. let decrypted_filled_sells: Vec<u16> = encrypted_sell_orders.iter().map(decrypt).collect();
  102. let decrypted_filled_buys: Vec<u16> = encrypted_buy_orders.iter().map(decrypt).collect();
  103. assert_eq!(decrypted_filled_sells, expected_filled_sells);
  104. assert_eq!(decrypted_filled_buys, expected_filled_buys);
  105. }