@@ -57,6 +57,52 @@ pub enum Policy<Pk: MiniscriptKey> {
5757 Threshold ( usize , Vec < Policy < Pk > > ) ,
5858}
5959
60+ /// Compute the Policy difference between two policies.
61+ /// This is useful when trying to find out the conditions
62+ /// under which the two policies are different.
63+ #[ derive( Debug , Clone ) ]
64+ pub struct PolicyDiff < Pk : MiniscriptKey > {
65+ /// The first policy
66+ pub a : Vec < Policy < Pk > > ,
67+ /// The second policy
68+ pub b : Vec < Policy < Pk > > ,
69+ }
70+
71+ impl < Pk : MiniscriptKey > PolicyDiff < Pk > {
72+ /// Combine two policy differences.
73+ // Policies should not generally contain repeated conditions,
74+ // therefore we do not many attempt to deal with those.
75+ pub fn combine ( & mut self , second : Self ) {
76+ self . a . extend ( second. a ) ;
77+ self . b . extend ( second. b ) ;
78+ }
79+
80+ // create a new diff directly without removing
81+ // same policies.
82+ fn _new ( a : Vec < Policy < Pk > > , b : Vec < Policy < Pk > > ) -> Self {
83+ Self { a, b }
84+ }
85+
86+ /// Create a new PolicyDiff in the
87+ pub fn new ( a : Policy < Pk > , b : Policy < Pk > ) -> Self {
88+ match ( a. normalized ( ) , b. normalized ( ) ) {
89+ ( x, y) if x == y => Self :: _new ( vec ! [ ] , vec ! [ ] ) ,
90+ ( Policy :: Threshold ( k1, subs1) , Policy :: Threshold ( k2, subs2) )
91+ if k1 == k2 && subs1. len ( ) == subs2. len ( ) =>
92+ {
93+ let mut a = Self :: _new ( vec ! [ ] , vec ! [ ] ) ;
94+
95+ for ( sub_a, sub_b) in subs1. into_iter ( ) . zip ( subs2. into_iter ( ) ) {
96+ let sub_diff = Self :: _new ( vec ! [ sub_a] , vec ! [ sub_b] ) ;
97+ a. combine ( sub_diff) ;
98+ }
99+ a
100+ }
101+ ( x, y) => Self :: _new ( vec ! [ x] , vec ! [ y] ) ,
102+ }
103+ }
104+ }
105+
60106impl < Pk : MiniscriptKey > ForEachKey < Pk > for Policy < Pk > {
61107 fn for_each_key < ' a , F : FnMut ( ForEach < ' a , Pk > ) -> bool > ( & ' a self , mut pred : F ) -> bool
62108 where
@@ -78,6 +124,42 @@ impl<Pk: MiniscriptKey> ForEachKey<Pk> for Policy<Pk> {
78124}
79125
80126impl < Pk : MiniscriptKey > Policy < Pk > {
127+ fn term_name ( & self ) -> String {
128+ match * self {
129+ Policy :: Threshold ( k, ref subs) => {
130+ if k == subs. len ( ) {
131+ String :: from ( format ! ( "and({},{})" , k, subs. len( ) ) )
132+ } else if k == 1 {
133+ String :: from ( format ! ( "or({},{})" , k, subs. len( ) ) )
134+ } else {
135+ String :: from ( format ! ( "thresh({},{})" , k, subs. len( ) ) )
136+ }
137+ }
138+ _ => self . to_string ( ) ,
139+ }
140+ }
141+
142+ fn _pprint_tree ( & self , prefix : String , last : bool ) {
143+ let prefix_current = if last { "`-- " } else { "|-- " } ;
144+
145+ println ! ( "{}{}{}" , prefix, prefix_current, self . term_name( ) ) ;
146+
147+ let prefix_child = if last { " " } else { "| " } ;
148+ let prefix = prefix + prefix_child;
149+
150+ if let Policy :: Threshold ( _k, ref subs) = * self {
151+ let last_child = subs. len ( ) - 1 ;
152+
153+ for ( i, child) in subs. iter ( ) . enumerate ( ) {
154+ child. _pprint_tree ( prefix. to_string ( ) , i == last_child) ;
155+ }
156+ }
157+ }
158+
159+ /// Pretty Print a tree
160+ pub fn pprint_tree ( & self ) {
161+ self . _pprint_tree ( "" . to_string ( ) , true ) ;
162+ }
81163 /// Convert a policy using one kind of public key to another
82164 /// type of public key
83165 pub fn translate_pkh < Fpkh , Q , E > ( & self , mut translatefpkh : Fpkh ) -> Result < Policy < Q > , E >
@@ -641,6 +723,8 @@ mod tests {
641723 // Very bad idea to add master key,pk but let's have it have 50M blocks
642724 let master_key = StringPolicy :: from_str ( "and(older(50000000),pkh(master))" ) . unwrap ( ) ;
643725 let new_liquid_pol = Policy :: Threshold ( 1 , vec ! [ liquid_pol. clone( ) , master_key] ) ;
726+ // Pretty print a policy
727+ // liquid_pol.pprint_tree();
644728
645729 assert ! ( liquid_pol. clone( ) . entails( new_liquid_pol. clone( ) ) . unwrap( ) ) ;
646730 assert ! ( !new_liquid_pol. entails( liquid_pol. clone( ) ) . unwrap( ) ) ;
0 commit comments