@@ -20,6 +20,7 @@ use crate::ergotree_interpreter::sigma_protocol::prover::hint::{Hint, HintsBag};
2020use alloc:: boxed:: Box ;
2121use alloc:: vec:: Vec ;
2222use ergotree_interpreter:: sigma_protocol:: private_input:: PrivateInput ;
23+ use ergotree_interpreter:: sigma_protocol:: prover:: hint:: CommitmentHint ;
2324use ergotree_interpreter:: sigma_protocol:: prover:: Prover ;
2425use ergotree_interpreter:: sigma_protocol:: prover:: ProverError ;
2526use 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