@@ -81,8 +81,8 @@ impl Policy {
8181 } )
8282 }
8383
84- /// Checks whether a set of signatures by all `keyhashes` would satisfy the quorum of this
85- /// policy.
84+ /// satisfies_quorum_policy checks whether a set of signatures by all keys corresponding to `keyhashes`
85+ /// would satisfy the quorum of this policy.
8686 /// This function does not check that those keyhashes actually signed anything.
8787 pub fn satisfies_quorum_policy ( & self , keyhashes : & [ Hash ] ) -> bool {
8888 match & self . quorum {
@@ -150,6 +150,7 @@ pub enum PolicyError {
150150 QuorumAlreadySet ,
151151}
152152
153+ #[ derive( Debug ) ]
153154pub struct PolicyBuilder ( Policy ) ;
154155
155156impl Default for PolicyBuilder {
@@ -167,21 +168,21 @@ impl PolicyBuilder {
167168 quorum : None ,
168169 } )
169170 }
170- pub fn add_log ( & mut self , key : PublicKey , url : Option < String > ) -> Result < ( ) , PolicyError > {
171+ pub fn add_log ( & mut self , key : PublicKey , url : Option < String > ) -> Result < & mut Self , PolicyError > {
171172 let keyhash = Hash :: new ( & key) ;
172173 if self . 0 . logs . contains_key ( & keyhash) {
173174 return Err ( PolicyError :: DuplicateLogKey ( key) ) ;
174175 }
175176 self . 0 . logs . insert ( keyhash, Entity ( key, url) ) ;
176- Ok ( ( ) )
177+ Ok ( self )
177178 }
178179
179180 pub fn add_witness (
180181 & mut self ,
181182 name : String ,
182183 key : PublicKey ,
183184 url : Option < String > ,
184- ) -> Result < ( ) , PolicyError > {
185+ ) -> Result < & mut Self , PolicyError > {
185186 let keyhash = Hash :: new ( & key) ;
186187 if self . 0 . witnesses . contains_key ( & keyhash) {
187188 return Err ( PolicyError :: DuplicateWitnessKey ( key) ) ;
@@ -191,15 +192,15 @@ impl PolicyBuilder {
191192 }
192193 self . 0 . witnesses . insert ( keyhash. clone ( ) , Entity ( key, url) ) ;
193194 self . 0 . quorums . insert ( name, Quorum :: Witness ( keyhash) ) ;
194- Ok ( ( ) )
195+ Ok ( self )
195196 }
196197
197198 pub fn add_group (
198199 & mut self ,
199200 name : String ,
200201 k : usize ,
201202 members : Vec < String > ,
202- ) -> Result < ( ) , PolicyError > {
203+ ) -> Result < & mut Self , PolicyError > {
203204 if self . 0 . quorums . contains_key ( & name) {
204205 return Err ( PolicyError :: DuplicateName ( name) ) ;
205206 }
@@ -209,18 +210,18 @@ impl PolicyBuilder {
209210 }
210211 }
211212 self . 0 . quorums . insert ( name, Quorum :: Group { k, members } ) ;
212- Ok ( ( ) )
213+ Ok ( self )
213214 }
214215
215- pub fn set_quorum ( & mut self , name : String ) -> Result < ( ) , PolicyError > {
216+ pub fn set_quorum ( & mut self , name : String ) -> Result < & mut Self , PolicyError > {
216217 if self . 0 . quorum . is_some ( ) {
217218 return Err ( PolicyError :: QuorumAlreadySet ) ;
218219 }
219220 if !self . 0 . quorums . contains_key ( & name) {
220221 return Err ( PolicyError :: UnknownName ( name) ) ;
221222 }
222223 self . 0 . quorum = Some ( name) ;
223- Ok ( ( ) )
224+ Ok ( self )
224225 }
225226
226227 pub fn build ( self ) -> Policy {
@@ -354,8 +355,8 @@ mod tests {
354355 hex ! ( "ec5681da2b676ab81df2daea3254cd8c4a5149318a62ae3bec6b4e80504b3b24" ) . into ( ) ;
355356 let mut builder = PolicyBuilder :: new ( ) ;
356357 builder. add_log ( key. clone ( ) , None ) . unwrap ( ) ;
357- let res = builder. add_log ( key. clone ( ) , Some ( "https://example.org" . into ( ) ) ) ;
358- assert_eq ! ( Err ( PolicyError :: DuplicateLogKey ( key) ) , res) ;
358+ let res = builder. add_log ( key. clone ( ) , Some ( "https://example.org" . into ( ) ) ) . unwrap_err ( ) ;
359+ assert_eq ! ( PolicyError :: DuplicateLogKey ( key) , res) ;
359360 insta:: assert_debug_snapshot!( builder. build( ) ) ;
360361 }
361362
@@ -371,8 +372,8 @@ mod tests {
371372 "mywitness2" . into ( ) ,
372373 key. clone ( ) ,
373374 Some ( "https://example.com" . into ( ) ) ,
374- ) ;
375- assert_eq ! ( Err ( PolicyError :: DuplicateWitnessKey ( key) ) , res) ;
375+ ) . unwrap_err ( ) ;
376+ assert_eq ! ( PolicyError :: DuplicateWitnessKey ( key) , res) ;
376377 insta:: assert_debug_snapshot!( builder. build( ) ) ;
377378 }
378379
@@ -386,28 +387,28 @@ mod tests {
386387 let mut builder = PolicyBuilder :: new ( ) ;
387388 builder. add_witness ( name. clone ( ) , key1, None ) . unwrap ( ) ;
388389
389- let res1 = builder. add_group ( name. clone ( ) , 1 , vec ! [ "foo" . into( ) ] ) ;
390- assert_eq ! ( Err ( PolicyError :: DuplicateName ( name. clone( ) ) ) , res1) ;
390+ let res1 = builder. add_group ( name. clone ( ) , 1 , vec ! [ "foo" . into( ) ] ) . unwrap_err ( ) ;
391+ assert_eq ! ( PolicyError :: DuplicateName ( name. clone( ) ) , res1) ;
391392
392- let res2 = builder. add_witness ( name. clone ( ) , key2, None ) ;
393- assert_eq ! ( Err ( PolicyError :: DuplicateName ( name) ) , res2) ;
393+ let res2 = builder. add_witness ( name. clone ( ) , key2, None ) . unwrap_err ( ) ;
394+ assert_eq ! ( PolicyError :: DuplicateName ( name) , res2) ;
394395
395396 insta:: assert_debug_snapshot!( builder. build( ) ) ;
396397 }
397398
398399 #[ test]
399400 fn uplicate_unknown_member_name ( ) {
400401 let mut builder = PolicyBuilder :: new ( ) ;
401- let res = builder. add_group ( "mygroup" . into ( ) , 1 , vec ! [ "mywitness" . into( ) ] ) ;
402- assert_eq ! ( Err ( PolicyError :: UnknownName ( "mywitness" . into( ) ) ) , res) ;
402+ let res = builder. add_group ( "mygroup" . into ( ) , 1 , vec ! [ "mywitness" . into( ) ] ) . unwrap_err ( ) ;
403+ assert_eq ! ( PolicyError :: UnknownName ( "mywitness" . into( ) ) , res) ;
403404 insta:: assert_debug_snapshot!( builder. build( ) ) ;
404405 }
405406
406407 #[ test]
407408 fn unknown_quorum_name ( ) {
408409 let mut builder = PolicyBuilder :: new ( ) ;
409- let res = builder. set_quorum ( "mywitness" . into ( ) ) ;
410- assert_eq ! ( Err ( PolicyError :: UnknownName ( "mywitness" . into( ) ) ) , res) ;
410+ let res = builder. set_quorum ( "mywitness" . into ( ) ) . unwrap_err ( ) ;
411+ assert_eq ! ( PolicyError :: UnknownName ( "mywitness" . into( ) ) , res) ;
411412 insta:: assert_debug_snapshot!( builder. build( ) ) ;
412413 }
413414
@@ -425,8 +426,104 @@ mod tests {
425426 . add_witness ( "mywitness2" . into ( ) , key2, None )
426427 . unwrap ( ) ;
427428 builder. set_quorum ( "mywitness1" . into ( ) ) . unwrap ( ) ;
428- let res = builder. set_quorum ( "mywitness2" . into ( ) ) ;
429- assert_eq ! ( Err ( PolicyError :: QuorumAlreadySet ) , res) ;
429+ let res = builder. set_quorum ( "mywitness2" . into ( ) ) . unwrap_err ( ) ;
430+ assert_eq ! ( PolicyError :: QuorumAlreadySet , res) ;
430431 assert_eq ! ( Some ( "mywitness1" . into( ) ) , builder. build( ) . quorum) ;
431432 }
433+
434+ #[ test]
435+ fn witness_quorum_satisfied ( ) {
436+ let key1: PublicKey =
437+ hex ! ( "ec5681da2b676ab81df2daea3254cd8c4a5149318a62ae3bec6b4e80504b3b24" ) . into ( ) ;
438+ let mut builder = PolicyBuilder :: new ( ) ;
439+ builder
440+ . add_witness ( "mywitness1" . into ( ) , key1. clone ( ) , None ) . unwrap ( )
441+ . set_quorum ( "mywitness1" . into ( ) ) . unwrap ( ) ;
442+ let policy = builder. build ( ) ;
443+
444+ assert ! ( policy. satisfies_quorum_policy( & [ Hash :: new( key1) ] ) ) ;
445+ }
446+
447+ #[ test]
448+ fn one_of_two_quorum_satisfied ( ) {
449+ let key1: PublicKey =
450+ hex ! ( "ec5681da2b676ab81df2daea3254cd8c4a5149318a62ae3bec6b4e80504b3b24" ) . into ( ) ;
451+ let key2: PublicKey =
452+ hex ! ( "d9440882ae2bd57076d4da2e7a12d4b26e137d56116419a69f8d6969709ed747" ) . into ( ) ;
453+ let mut builder = PolicyBuilder :: new ( ) ;
454+ builder
455+ . add_witness ( "mywitness1" . into ( ) , key1. clone ( ) , None )
456+ . unwrap ( )
457+ . add_witness ( "mywitness2" . into ( ) , key2, None )
458+ . unwrap ( )
459+ . add_group ( String :: from ( "myquorum" ) , 1 , vec ! [ "mywitness1" . to_string( ) , "mywitness2" . to_string( ) ] ) . unwrap ( )
460+ . set_quorum ( "myquorum" . into ( ) ) . unwrap ( ) ;
461+ let policy = builder. build ( ) ;
462+
463+ assert ! ( policy. satisfies_quorum_policy( & [ Hash :: new( key1) ] ) ) ;
464+ }
465+
466+ #[ test]
467+ fn complex_quorum_satisfied ( ) {
468+ let key1: PublicKey =
469+ hex ! ( "ec5681da2b676ab81df2daea3254cd8c4a5149318a62ae3bec6b4e80504b3b24" ) . into ( ) ;
470+ let key2: PublicKey =
471+ hex ! ( "d9440882ae2bd57076d4da2e7a12d4b26e137d56116419a69f8d6969709ed747" ) . into ( ) ;
472+ let key3: PublicKey =
473+ hex ! ( "ac5681da2b676ab81df2daea3254cd8c4a5149318a62ae3bec6b4e80504b3b24" ) . into ( ) ;
474+ let key4: PublicKey =
475+ hex ! ( "b9440882ae2bd57076d4da2e7a12d4b26e137d56116419a69f8d6969709ed747" ) . into ( ) ;
476+ let key5: PublicKey =
477+ hex ! ( "aa5681da2b676ab81df2daea3254cd8c4a5149318a62ae3bec6b4e80504b3b24" ) . into ( ) ;
478+ let key6: PublicKey =
479+ hex ! ( "bc440882ae2bd57076d4da2e7a12d4b26e137d56116419a69f8d6969709ed747" ) . into ( ) ;
480+ let key7: PublicKey =
481+ hex ! ( "bc440882ae2bd57076d4da2e7a12d4b26e137d56116419a69f8d6969709ed74a" ) . into ( ) ;
482+
483+ let mut builder = PolicyBuilder :: new ( ) ;
484+
485+ builder
486+ . add_witness ( "mywitness1" . into ( ) , key1. clone ( ) , None )
487+ . unwrap ( )
488+ . add_witness ( "mywitness2" . into ( ) , key2. clone ( ) , None )
489+ . unwrap ( )
490+ . add_group ( String :: from ( "group1" ) , 1 , vec ! [ "mywitness1" . to_string( ) , "mywitness2" . to_string( ) ] ) . unwrap ( ) ;
491+
492+ builder
493+ . add_witness ( "mywitness3" . into ( ) , key3. clone ( ) , None )
494+ . unwrap ( )
495+ . add_witness ( "mywitness4" . into ( ) , key4. clone ( ) , None )
496+ . unwrap ( )
497+ . add_group ( String :: from ( "group2" ) , 2 , vec ! [ "mywitness3" . to_string( ) , "mywitness4" . to_string( ) ] ) . unwrap ( ) ;
498+
499+ builder
500+ . add_witness ( "mywitness5" . into ( ) , key5. clone ( ) , None )
501+ . unwrap ( )
502+ . add_witness ( "mywitness6" . into ( ) , key6. clone ( ) , None )
503+ . unwrap ( )
504+ . add_witness ( "mywitness7" . into ( ) , key7. clone ( ) , None )
505+ . unwrap ( )
506+ . add_group ( String :: from ( "group3" ) , 2 , vec ! [ "mywitness5" . to_string( ) , "mywitness6" . to_string( ) , "mywitness7" . to_string( ) ] ) . unwrap ( ) ;
507+
508+ builder
509+ . add_group ( String :: from ( "finalgroup" ) , 2 , vec ! [ "group1" . to_string( ) , "group2" . to_string( ) , "group3" . to_string( ) ] ) . unwrap ( )
510+ . set_quorum ( String :: from ( "finalgroup" ) ) . unwrap ( ) ;
511+
512+ let policy = builder. build ( ) ;
513+
514+ assert ! ( policy. satisfies_quorum_policy( & [ Hash :: new( & key1) , Hash :: new( & key3) , Hash :: new( & key4) ] ) ) ;
515+
516+ assert ! ( !policy. satisfies_quorum_policy( & [ Hash :: new( & key1) , Hash :: new( & key3) , Hash :: new( & key5) ] ) ) ;
517+
518+ assert ! ( policy. satisfies_quorum_policy( & [ Hash :: new( & key1) , Hash :: new( & key3) , Hash :: new( & key5) , Hash :: new( & key6) ] ) ) ;
519+
520+ assert ! ( !policy. satisfies_quorum_policy( & [ Hash :: new( & key3) , Hash :: new( & key4) ] ) ) ;
521+
522+ assert ! ( policy. satisfies_quorum_policy( & [ Hash :: new( & key3) , Hash :: new( & key4) , Hash :: new( & key5) , Hash :: new( & key7) ] ) ) ;
523+
524+ assert ! ( policy. satisfies_quorum_policy( & [ Hash :: new( & key1) , Hash :: new( & key3) , Hash :: new( & key4) , Hash :: new( & key7) , Hash :: new( & key5) ] ) ) ;
525+
526+ assert ! ( !policy. satisfies_quorum_policy( & [ Hash :: new( & key3) , Hash :: new( & key4) , Hash :: new( & key6) ] ) ) ;
527+ }
528+
432529}
0 commit comments