| 637 | } |
| 638 | |
| 639 | fn compute_initial<R: RngCore>( |
| 640 | rng: &mut R, |
| 641 | max_size: u64, |
| 642 | sk: &SecretKey<G::ScalarField>, |
| 643 | xs: Vec<G::ScalarField>, |
| 644 | initial_elements_store: &mut dyn InitialElementsStore<G::ScalarField>, |
| 645 | ) -> G::ScalarField { |
| 646 | let mut f_V = G::ScalarField::one(); |
| 647 | for x in xs { |
| 648 | f_V *= x + sk.0; |
| 649 | initial_elements_store.add(x); |
| 650 | } |
| 651 | |
| 652 | // We need more secret elements than known elements (in case all witness holders collude). As there can |
| 653 | // be at most `max_size` witnesses, there must be at least `max_size + 1` initial elements secret. |
| 654 | // It's assumed that elements in `xs` are public constants and thus `max_size + 1` more random elements are generated. |
| 655 | // Thus there are `max_size + xs.len() + 1` initial elements in total. However, if `xs` could be assumed |
| 656 | // secret, then only `max_size - xs.len() + 1` random elements need to be generated. |
| 657 | // Accepting an argument indicating whether `xs` is public could be another way to solve it |
| 658 | // but as `xs.len <<< max_size` in practice, didn't feel right to make the function accept |
| 659 | // one more argument and make caller decide one more thing. |
| 660 | for _ in 0..(max_size + 1) { |
| 661 | let elem = G::ScalarField::rand(rng); |
| 662 | f_V *= elem + sk.0; |
| 663 | initial_elements_store.add(elem); |
| 664 | } |
| 665 | f_V |
| 666 | } |
| 667 | |
| 668 | fn compute_random_initial<R: RngCore>( |
| 669 | rng: &mut R, |