Skip to content

Commit 5a070af

Browse files
DioBr4nd0sethdusek
authored andcommitted
fix:updated the transactionhintsbag implemntation for public and private hints
1 parent 2f840d3 commit 5a070af

File tree

1 file changed

+53
-46
lines changed

1 file changed

+53
-46
lines changed

ergo-lib/src/wallet.rs

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::ergotree_interpreter::sigma_protocol::prover::hint::{Hint, HintsBag};
2020
use alloc::boxed::Box;
2121
use alloc::vec::Vec;
2222
use ergotree_interpreter::sigma_protocol::private_input::PrivateInput;
23+
use ergotree_interpreter::sigma_protocol::prover::hint::CommitmentHint;
2324
use ergotree_interpreter::sigma_protocol::prover::Prover;
2425
use ergotree_interpreter::sigma_protocol::prover::ProverError;
2526
use ergotree_interpreter::sigma_protocol::prover::TestProver;
@@ -282,66 +283,72 @@ impl TransactionHintsBag {
282283
}
283284
}
284285

286+
/// Private helper function to correctly segregate a HintsBag into secret and public parts.
287+
fn segregate_hints(hints_bag: HintsBag) -> (HintsBag, HintsBag) {
288+
let (secret, public): (Vec<Hint>, Vec<Hint>) =
289+
hints_bag.hints.into_iter().partition(|hint| {
290+
matches!(hint, Hint::CommitmentHint(CommitmentHint::OwnCommitment(_)))
291+
});
292+
293+
(HintsBag { hints: secret }, HintsBag { hints: public })
294+
}
295+
285296
/// Replacing Hints for an input index
286297
pub fn replace_hints_for_input(&mut self, index: usize, hints_bag: HintsBag) {
287-
let public: Vec<Hint> = hints_bag
288-
.hints
289-
.clone()
290-
.into_iter()
291-
.filter(|hint| matches!(hint, Hint::CommitmentHint(_)))
292-
.collect();
293-
let secret: Vec<Hint> = hints_bag
294-
.hints
295-
.into_iter()
296-
.filter(|hint| matches!(hint, Hint::SecretProven(_)))
297-
.collect();
298-
299-
self.secret_hints.insert(index, HintsBag { hints: secret });
300-
self.public_hints.insert(index, HintsBag { hints: public });
298+
let (secret_bag, public_bag) = Self::segregate_hints(hints_bag);
299+
self.secret_hints.insert(index, secret_bag);
300+
self.public_hints.insert(index, public_bag);
301301
}
302302

303303
/// Adding hints for a input index
304304
pub fn add_hints_for_input(&mut self, index: usize, hints_bag: HintsBag) {
305-
let mut public: Vec<Hint> = hints_bag
306-
.hints
307-
.clone()
308-
.into_iter()
309-
.filter(|hint| matches!(hint, Hint::CommitmentHint(_)))
310-
.collect();
311-
let mut secret: Vec<Hint> = hints_bag
312-
.hints
313-
.into_iter()
314-
.filter(|hint| matches!(hint, Hint::SecretProven(_)))
315-
.collect();
316-
let secret_bag = HintsBag::empty();
317-
let public_bag = HintsBag::empty();
318-
let old_secret: &Vec<Hint> = &self.secret_hints.get(&index).unwrap_or(&secret_bag).hints;
319-
for hint in old_secret {
320-
secret.push(hint.clone());
305+
let (mut new_secret_bag, mut new_public_bag) = Self::segregate_hints(hints_bag);
306+
307+
// Get the existing secret hints, or an empty bag if none exist, and add the new ones.
308+
if let Some(existing_secrets) = self.secret_hints.get_mut(&index) {
309+
existing_secrets.hints.append(&mut new_secret_bag.hints);
310+
} else {
311+
self.secret_hints.insert(index, new_secret_bag);
321312
}
322313

323-
let old_public: &Vec<Hint> = &self.public_hints.get(&index).unwrap_or(&public_bag).hints;
324-
for hint in old_public {
325-
public.push(hint.clone());
314+
// Get the existing public hints, or an empty bag if none exist, and add the new ones.
315+
if let Some(existing_public) = self.public_hints.get_mut(&index) {
316+
existing_public.hints.append(&mut new_public_bag.hints);
317+
} else {
318+
self.public_hints.insert(index, new_public_bag);
326319
}
327-
self.secret_hints.insert(index, HintsBag { hints: secret });
328-
self.public_hints.insert(index, HintsBag { hints: public });
329320
}
330321

331322
/// Outputting HintsBag corresponding for an index
323+
/// WARNING: This HintsBag also contains private randomness that should not be shared with other signers
332324
pub fn all_hints_for_input(&self, index: usize) -> HintsBag {
333-
let mut hints: Vec<Hint> = Vec::new();
334-
let secret_bag = HintsBag::empty();
335-
let public_bag = HintsBag::empty();
336-
let secrets: &Vec<Hint> = &self.secret_hints.get(&index).unwrap_or(&secret_bag).hints;
337-
for hint in secrets {
338-
hints.push(hint.clone());
325+
let mut all_hints = Vec::new();
326+
327+
if let Some(secret_bag) = self.secret_hints.get(&index) {
328+
all_hints.extend_from_slice(&secret_bag.hints);
329+
}
330+
331+
if let Some(public_bag) = self.public_hints.get(&index) {
332+
all_hints.extend_from_slice(&public_bag.hints);
339333
}
340-
let public: &Vec<Hint> = &self.public_hints.get(&index).unwrap_or(&public_bag).hints;
341-
for hint in public {
342-
hints.push(hint.clone());
334+
335+
HintsBag { hints: all_hints }
336+
}
337+
}
338+
339+
#[cfg(test)]
340+
#[cfg(feature = "arbitrary")]
341+
mod test {
342+
use ergotree_interpreter::sigma_protocol::prover::hint::{CommitmentHint, Hint, HintsBag};
343+
use proptest::prelude::*;
344+
345+
use crate::wallet::TransactionHintsBag;
346+
proptest! {
347+
#[test]
348+
fn test_segregate(hints in any::<HintsBag>()) {
349+
let (secret, public) = TransactionHintsBag::segregate_hints(hints);
350+
assert!(secret.hints.iter().all(|hint| matches!(hint, Hint::CommitmentHint(CommitmentHint::OwnCommitment(_)))));
351+
assert!(public.hints.iter().all(|hint| !matches!(hint, Hint::CommitmentHint(CommitmentHint::OwnCommitment(_)))));
343352
}
344-
let hints_bag: HintsBag = HintsBag { hints };
345-
hints_bag
346353
}
347354
}

0 commit comments

Comments
 (0)