verify_proofs.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. #![allow(clippy::arithmetic_side_effects)]
  2. // Allow deprecated warnings since this crate will be removed along with
  3. // `solana-zk-token-sdk` will be removed
  4. #![allow(deprecated)]
  5. use {
  6. criterion::{criterion_group, criterion_main, Criterion},
  7. curve25519_dalek::scalar::Scalar,
  8. solana_zk_token_sdk::{
  9. encryption::{
  10. elgamal::ElGamalKeypair,
  11. grouped_elgamal::GroupedElGamal,
  12. pedersen::{Pedersen, PedersenOpening},
  13. },
  14. instruction::{
  15. transfer::FeeParameters, BatchedGroupedCiphertext2HandlesValidityProofData,
  16. BatchedGroupedCiphertext3HandlesValidityProofData, BatchedRangeProofU128Data,
  17. BatchedRangeProofU256Data, BatchedRangeProofU64Data,
  18. CiphertextCiphertextEqualityProofData, CiphertextCommitmentEqualityProofData,
  19. FeeSigmaProofData, GroupedCiphertext2HandlesValidityProofData,
  20. GroupedCiphertext3HandlesValidityProofData, PubkeyValidityData, RangeProofU64Data,
  21. TransferData, TransferWithFeeData, WithdrawData, ZeroBalanceProofData, ZkProofData,
  22. },
  23. },
  24. };
  25. fn bench_pubkey_validity(c: &mut Criterion) {
  26. let keypair = ElGamalKeypair::new_rand();
  27. let proof_data = PubkeyValidityData::new(&keypair).unwrap();
  28. c.bench_function("pubkey_validity", |b| {
  29. b.iter(|| {
  30. proof_data.verify_proof().unwrap();
  31. })
  32. });
  33. }
  34. fn bench_range_proof_u64(c: &mut Criterion) {
  35. let amount = u64::MAX;
  36. let (commitment, opening) = Pedersen::new(amount);
  37. let proof_data = RangeProofU64Data::new(&commitment, amount, &opening).unwrap();
  38. c.bench_function("range_proof_u64", |b| {
  39. b.iter(|| {
  40. proof_data.verify_proof().unwrap();
  41. })
  42. });
  43. }
  44. fn bench_withdraw(c: &mut Criterion) {
  45. let keypair = ElGamalKeypair::new_rand();
  46. let current_balance: u64 = 77;
  47. let current_ciphertext = keypair.pubkey().encrypt(current_balance);
  48. let withdraw_amount: u64 = 55;
  49. let proof_data = WithdrawData::new(
  50. withdraw_amount,
  51. &keypair,
  52. current_balance,
  53. &current_ciphertext,
  54. )
  55. .unwrap();
  56. c.bench_function("withdraw", |b| {
  57. b.iter(|| {
  58. proof_data.verify_proof().unwrap();
  59. })
  60. });
  61. }
  62. fn bench_zero_balance(c: &mut Criterion) {
  63. let keypair = ElGamalKeypair::new_rand();
  64. let ciphertext = keypair.pubkey().encrypt(0_u64);
  65. let proof_data = ZeroBalanceProofData::new(&keypair, &ciphertext).unwrap();
  66. c.bench_function("zero_balance", |b| {
  67. b.iter(|| {
  68. proof_data.verify_proof().unwrap();
  69. })
  70. });
  71. }
  72. fn bench_grouped_ciphertext_2_handles_validity(c: &mut Criterion) {
  73. let destination_keypair = ElGamalKeypair::new_rand();
  74. let destination_pubkey = destination_keypair.pubkey();
  75. let auditor_keypair = ElGamalKeypair::new_rand();
  76. let auditor_pubkey = auditor_keypair.pubkey();
  77. let amount: u64 = 55;
  78. let opening = PedersenOpening::new_rand();
  79. let grouped_ciphertext =
  80. GroupedElGamal::encrypt_with([destination_pubkey, auditor_pubkey], amount, &opening);
  81. let proof_data = GroupedCiphertext2HandlesValidityProofData::new(
  82. destination_pubkey,
  83. auditor_pubkey,
  84. &grouped_ciphertext,
  85. amount,
  86. &opening,
  87. )
  88. .unwrap();
  89. c.bench_function("grouped_ciphertext_2_handles_validity", |b| {
  90. b.iter(|| {
  91. proof_data.verify_proof().unwrap();
  92. })
  93. });
  94. }
  95. fn bench_grouped_ciphertext_3_handles_validity(c: &mut Criterion) {
  96. let source_keypair = ElGamalKeypair::new_rand();
  97. let source_pubkey = source_keypair.pubkey();
  98. let destination_keypair = ElGamalKeypair::new_rand();
  99. let destination_pubkey = destination_keypair.pubkey();
  100. let auditor_keypair = ElGamalKeypair::new_rand();
  101. let auditor_pubkey = auditor_keypair.pubkey();
  102. let amount: u64 = 55;
  103. let opening = PedersenOpening::new_rand();
  104. let grouped_ciphertext = GroupedElGamal::encrypt_with(
  105. [source_pubkey, destination_pubkey, auditor_pubkey],
  106. amount,
  107. &opening,
  108. );
  109. let proof_data = GroupedCiphertext3HandlesValidityProofData::new(
  110. source_pubkey,
  111. destination_pubkey,
  112. auditor_pubkey,
  113. &grouped_ciphertext,
  114. amount,
  115. &opening,
  116. )
  117. .unwrap();
  118. c.bench_function("grouped_ciphertext_3_handles_validity", |b| {
  119. b.iter(|| {
  120. proof_data.verify_proof().unwrap();
  121. })
  122. });
  123. }
  124. fn bench_ciphertext_commitment_equality(c: &mut Criterion) {
  125. let keypair = ElGamalKeypair::new_rand();
  126. let amount: u64 = 55;
  127. let ciphertext = keypair.pubkey().encrypt(amount);
  128. let (commitment, opening) = Pedersen::new(amount);
  129. let proof_data = CiphertextCommitmentEqualityProofData::new(
  130. &keypair,
  131. &ciphertext,
  132. &commitment,
  133. &opening,
  134. amount,
  135. )
  136. .unwrap();
  137. c.bench_function("ciphertext_commitment_equality", |b| {
  138. b.iter(|| {
  139. proof_data.verify_proof().unwrap();
  140. })
  141. });
  142. }
  143. fn bench_ciphertext_ciphertext_equality(c: &mut Criterion) {
  144. let source_keypair = ElGamalKeypair::new_rand();
  145. let destination_keypair = ElGamalKeypair::new_rand();
  146. let amount: u64 = 0;
  147. let source_ciphertext = source_keypair.pubkey().encrypt(amount);
  148. let destination_opening = PedersenOpening::new_rand();
  149. let destination_ciphertext = destination_keypair
  150. .pubkey()
  151. .encrypt_with(amount, &destination_opening);
  152. let proof_data = CiphertextCiphertextEqualityProofData::new(
  153. &source_keypair,
  154. destination_keypair.pubkey(),
  155. &source_ciphertext,
  156. &destination_ciphertext,
  157. &destination_opening,
  158. amount,
  159. )
  160. .unwrap();
  161. c.bench_function("ciphertext_ciphertext_equality", |b| {
  162. b.iter(|| {
  163. proof_data.verify_proof().unwrap();
  164. })
  165. });
  166. }
  167. fn bench_batched_grouped_ciphertext_2_handles_validity(c: &mut Criterion) {
  168. let destination_keypair = ElGamalKeypair::new_rand();
  169. let destination_pubkey = destination_keypair.pubkey();
  170. let auditor_keypair = ElGamalKeypair::new_rand();
  171. let auditor_pubkey = auditor_keypair.pubkey();
  172. let amount_lo: u64 = 11;
  173. let amount_hi: u64 = 22;
  174. let opening_lo = PedersenOpening::new_rand();
  175. let opening_hi = PedersenOpening::new_rand();
  176. let grouped_ciphertext_lo =
  177. GroupedElGamal::encrypt_with([destination_pubkey, auditor_pubkey], amount_lo, &opening_lo);
  178. let grouped_ciphertext_hi =
  179. GroupedElGamal::encrypt_with([destination_pubkey, auditor_pubkey], amount_hi, &opening_hi);
  180. let proof_data = BatchedGroupedCiphertext2HandlesValidityProofData::new(
  181. destination_pubkey,
  182. auditor_pubkey,
  183. &grouped_ciphertext_lo,
  184. &grouped_ciphertext_hi,
  185. amount_lo,
  186. amount_hi,
  187. &opening_lo,
  188. &opening_hi,
  189. )
  190. .unwrap();
  191. c.bench_function("batched_grouped_ciphertext_validity", |b| {
  192. b.iter(|| {
  193. proof_data.verify_proof().unwrap();
  194. })
  195. });
  196. }
  197. fn bench_batched_grouped_ciphertext_3_handles_validity(c: &mut Criterion) {
  198. let source_keypair = ElGamalKeypair::new_rand();
  199. let source_pubkey = source_keypair.pubkey();
  200. let destination_keypair = ElGamalKeypair::new_rand();
  201. let destination_pubkey = destination_keypair.pubkey();
  202. let auditor_keypair = ElGamalKeypair::new_rand();
  203. let auditor_pubkey = auditor_keypair.pubkey();
  204. let amount_lo: u64 = 11;
  205. let amount_hi: u64 = 22;
  206. let opening_lo = PedersenOpening::new_rand();
  207. let opening_hi = PedersenOpening::new_rand();
  208. let grouped_ciphertext_lo = GroupedElGamal::encrypt_with(
  209. [source_pubkey, destination_pubkey, auditor_pubkey],
  210. amount_lo,
  211. &opening_lo,
  212. );
  213. let grouped_ciphertext_hi = GroupedElGamal::encrypt_with(
  214. [source_pubkey, destination_pubkey, auditor_pubkey],
  215. amount_hi,
  216. &opening_hi,
  217. );
  218. let proof_data = BatchedGroupedCiphertext3HandlesValidityProofData::new(
  219. source_pubkey,
  220. destination_pubkey,
  221. auditor_pubkey,
  222. &grouped_ciphertext_lo,
  223. &grouped_ciphertext_hi,
  224. amount_lo,
  225. amount_hi,
  226. &opening_lo,
  227. &opening_hi,
  228. )
  229. .unwrap();
  230. c.bench_function("batched_grouped_ciphertext_3_handles_validity", |b| {
  231. b.iter(|| {
  232. proof_data.verify_proof().unwrap();
  233. })
  234. });
  235. }
  236. #[allow(clippy::op_ref)]
  237. fn bench_fee_sigma(c: &mut Criterion) {
  238. let transfer_amount: u64 = 1;
  239. let max_fee: u64 = 3;
  240. let fee_rate: u16 = 400;
  241. let fee_amount: u64 = 1;
  242. let delta_fee: u64 = 9600;
  243. let (transfer_commitment, transfer_opening) = Pedersen::new(transfer_amount);
  244. let (fee_commitment, fee_opening) = Pedersen::new(fee_amount);
  245. let scalar_rate = Scalar::from(fee_rate);
  246. let delta_commitment =
  247. &fee_commitment * Scalar::from(10_000_u64) - &transfer_commitment * &scalar_rate;
  248. let delta_opening = &fee_opening * &Scalar::from(10_000_u64) - &transfer_opening * &scalar_rate;
  249. let (claimed_commitment, claimed_opening) = Pedersen::new(delta_fee);
  250. let proof_data = FeeSigmaProofData::new(
  251. &fee_commitment,
  252. &delta_commitment,
  253. &claimed_commitment,
  254. &fee_opening,
  255. &delta_opening,
  256. &claimed_opening,
  257. fee_amount,
  258. delta_fee,
  259. max_fee,
  260. )
  261. .unwrap();
  262. c.bench_function("fee_sigma", |b| {
  263. b.iter(|| {
  264. proof_data.verify_proof().unwrap();
  265. })
  266. });
  267. }
  268. fn bench_batched_range_proof_u64(c: &mut Criterion) {
  269. let amount_1 = 255_u64;
  270. let amount_2 = 77_u64;
  271. let amount_3 = 99_u64;
  272. let amount_4 = 99_u64;
  273. let amount_5 = 11_u64;
  274. let amount_6 = 33_u64;
  275. let amount_7 = 99_u64;
  276. let amount_8 = 99_u64;
  277. let (commitment_1, opening_1) = Pedersen::new(amount_1);
  278. let (commitment_2, opening_2) = Pedersen::new(amount_2);
  279. let (commitment_3, opening_3) = Pedersen::new(amount_3);
  280. let (commitment_4, opening_4) = Pedersen::new(amount_4);
  281. let (commitment_5, opening_5) = Pedersen::new(amount_5);
  282. let (commitment_6, opening_6) = Pedersen::new(amount_6);
  283. let (commitment_7, opening_7) = Pedersen::new(amount_7);
  284. let (commitment_8, opening_8) = Pedersen::new(amount_8);
  285. let proof_data = BatchedRangeProofU64Data::new(
  286. vec![
  287. &commitment_1,
  288. &commitment_2,
  289. &commitment_3,
  290. &commitment_4,
  291. &commitment_5,
  292. &commitment_6,
  293. &commitment_7,
  294. &commitment_8,
  295. ],
  296. vec![
  297. amount_1, amount_2, amount_3, amount_4, amount_5, amount_6, amount_7, amount_8,
  298. ],
  299. vec![8, 8, 8, 8, 8, 8, 8, 8],
  300. vec![
  301. &opening_1, &opening_2, &opening_3, &opening_4, &opening_5, &opening_6, &opening_7,
  302. &opening_8,
  303. ],
  304. )
  305. .unwrap();
  306. c.bench_function("batched_range_proof_u64", |b| {
  307. b.iter(|| {
  308. proof_data.verify_proof().unwrap();
  309. })
  310. });
  311. }
  312. fn bench_batched_range_proof_u128(c: &mut Criterion) {
  313. let amount_1 = 65535_u64;
  314. let amount_2 = 77_u64;
  315. let amount_3 = 99_u64;
  316. let amount_4 = 99_u64;
  317. let amount_5 = 11_u64;
  318. let amount_6 = 33_u64;
  319. let amount_7 = 99_u64;
  320. let amount_8 = 99_u64;
  321. let (commitment_1, opening_1) = Pedersen::new(amount_1);
  322. let (commitment_2, opening_2) = Pedersen::new(amount_2);
  323. let (commitment_3, opening_3) = Pedersen::new(amount_3);
  324. let (commitment_4, opening_4) = Pedersen::new(amount_4);
  325. let (commitment_5, opening_5) = Pedersen::new(amount_5);
  326. let (commitment_6, opening_6) = Pedersen::new(amount_6);
  327. let (commitment_7, opening_7) = Pedersen::new(amount_7);
  328. let (commitment_8, opening_8) = Pedersen::new(amount_8);
  329. let proof_data = BatchedRangeProofU128Data::new(
  330. vec![
  331. &commitment_1,
  332. &commitment_2,
  333. &commitment_3,
  334. &commitment_4,
  335. &commitment_5,
  336. &commitment_6,
  337. &commitment_7,
  338. &commitment_8,
  339. ],
  340. vec![
  341. amount_1, amount_2, amount_3, amount_4, amount_5, amount_6, amount_7, amount_8,
  342. ],
  343. vec![16, 16, 16, 16, 16, 16, 16, 16],
  344. vec![
  345. &opening_1, &opening_2, &opening_3, &opening_4, &opening_5, &opening_6, &opening_7,
  346. &opening_8,
  347. ],
  348. )
  349. .unwrap();
  350. c.bench_function("batched_range_proof_u128", |b| {
  351. b.iter(|| {
  352. proof_data.verify_proof().unwrap();
  353. })
  354. });
  355. }
  356. fn bench_batched_range_proof_u256(c: &mut Criterion) {
  357. let amount_1 = 4294967295_u64;
  358. let amount_2 = 77_u64;
  359. let amount_3 = 99_u64;
  360. let amount_4 = 99_u64;
  361. let amount_5 = 11_u64;
  362. let amount_6 = 33_u64;
  363. let amount_7 = 99_u64;
  364. let amount_8 = 99_u64;
  365. let (commitment_1, opening_1) = Pedersen::new(amount_1);
  366. let (commitment_2, opening_2) = Pedersen::new(amount_2);
  367. let (commitment_3, opening_3) = Pedersen::new(amount_3);
  368. let (commitment_4, opening_4) = Pedersen::new(amount_4);
  369. let (commitment_5, opening_5) = Pedersen::new(amount_5);
  370. let (commitment_6, opening_6) = Pedersen::new(amount_6);
  371. let (commitment_7, opening_7) = Pedersen::new(amount_7);
  372. let (commitment_8, opening_8) = Pedersen::new(amount_8);
  373. let proof_data = BatchedRangeProofU256Data::new(
  374. vec![
  375. &commitment_1,
  376. &commitment_2,
  377. &commitment_3,
  378. &commitment_4,
  379. &commitment_5,
  380. &commitment_6,
  381. &commitment_7,
  382. &commitment_8,
  383. ],
  384. vec![
  385. amount_1, amount_2, amount_3, amount_4, amount_5, amount_6, amount_7, amount_8,
  386. ],
  387. vec![32, 32, 32, 32, 32, 32, 32, 32],
  388. vec![
  389. &opening_1, &opening_2, &opening_3, &opening_4, &opening_5, &opening_6, &opening_7,
  390. &opening_8,
  391. ],
  392. )
  393. .unwrap();
  394. c.bench_function("batched_range_proof_u256", |b| {
  395. b.iter(|| {
  396. proof_data.verify_proof().unwrap();
  397. })
  398. });
  399. }
  400. fn bench_transfer(c: &mut Criterion) {
  401. let source_keypair = ElGamalKeypair::new_rand();
  402. let destination_keypair = ElGamalKeypair::new_rand();
  403. let destination_pubkey = destination_keypair.pubkey();
  404. let auditor_keypair = ElGamalKeypair::new_rand();
  405. let auditor_pubkey = auditor_keypair.pubkey();
  406. let spendable_balance: u64 = 77;
  407. let spendable_ciphertext = source_keypair.pubkey().encrypt(spendable_balance);
  408. let transfer_amount: u64 = 55;
  409. let proof_data = TransferData::new(
  410. transfer_amount,
  411. (spendable_balance, &spendable_ciphertext),
  412. &source_keypair,
  413. (destination_pubkey, auditor_pubkey),
  414. )
  415. .unwrap();
  416. c.bench_function("transfer", |b| {
  417. b.iter(|| {
  418. proof_data.verify_proof().unwrap();
  419. })
  420. });
  421. }
  422. fn bench_transfer_with_fee(c: &mut Criterion) {
  423. let source_keypair = ElGamalKeypair::new_rand();
  424. let destination_keypair = ElGamalKeypair::new_rand();
  425. let destination_pubkey = destination_keypair.pubkey();
  426. let auditor_keypair = ElGamalKeypair::new_rand();
  427. let auditor_pubkey = auditor_keypair.pubkey();
  428. let withdraw_withheld_authority_keypair = ElGamalKeypair::new_rand();
  429. let withdraw_withheld_authority_pubkey = withdraw_withheld_authority_keypair.pubkey();
  430. let spendable_balance: u64 = 120;
  431. let spendable_ciphertext = source_keypair.pubkey().encrypt(spendable_balance);
  432. let transfer_amount: u64 = 100;
  433. let fee_parameters = FeeParameters {
  434. fee_rate_basis_points: 400,
  435. maximum_fee: 3,
  436. };
  437. let proof_data = TransferWithFeeData::new(
  438. transfer_amount,
  439. (spendable_balance, &spendable_ciphertext),
  440. &source_keypair,
  441. (destination_pubkey, auditor_pubkey),
  442. fee_parameters,
  443. withdraw_withheld_authority_pubkey,
  444. )
  445. .unwrap();
  446. c.bench_function("transfer_with_fee", |b| {
  447. b.iter(|| {
  448. proof_data.verify_proof().unwrap();
  449. })
  450. });
  451. }
  452. criterion_group!(
  453. benches,
  454. bench_pubkey_validity,
  455. bench_range_proof_u64,
  456. bench_withdraw,
  457. bench_zero_balance,
  458. bench_grouped_ciphertext_2_handles_validity,
  459. bench_grouped_ciphertext_3_handles_validity,
  460. bench_ciphertext_commitment_equality,
  461. bench_ciphertext_ciphertext_equality,
  462. bench_batched_grouped_ciphertext_2_handles_validity,
  463. bench_batched_grouped_ciphertext_3_handles_validity,
  464. bench_batched_range_proof_u64,
  465. bench_batched_range_proof_u128,
  466. bench_batched_range_proof_u256,
  467. bench_transfer,
  468. bench_transfer_with_fee,
  469. bench_fee_sigma,
  470. );
  471. criterion_main!(benches);