@@ -119,7 +119,9 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
119119 && c. real_for_each_key ( pred)
120120 }
121121 Terminal :: Thresh ( _, ref subs) => subs. iter ( ) . all ( |sub| sub. real_for_each_key ( pred) ) ,
122- Terminal :: Multi ( _, ref keys) => keys. iter ( ) . all ( |key| pred ( ForEach :: Key ( key) ) ) ,
122+ Terminal :: Multi ( _, ref keys) | Terminal :: MultiA ( _, ref keys) => {
123+ keys. iter ( ) . all ( |key| pred ( ForEach :: Key ( key) ) )
124+ }
123125 }
124126 }
125127 pub ( super ) fn real_translate_pk < FPk , FPkh , Q , Error > (
@@ -209,6 +211,10 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
209211 let keys: Result < Vec < Q > , _ > = keys. iter ( ) . map ( & mut * translatefpk) . collect ( ) ;
210212 Terminal :: Multi ( k, keys?)
211213 }
214+ Terminal :: MultiA ( k, ref keys) => {
215+ let keys: Result < Vec < Q > , _ > = keys. iter ( ) . map ( & mut * translatefpk) . collect ( ) ;
216+ Terminal :: MultiA ( k, keys?)
217+ }
212218 } ;
213219 Ok ( frag)
214220 }
@@ -312,6 +318,13 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Debug for Terminal<Pk, Ctx> {
312318 }
313319 f. write_str ( ")" )
314320 }
321+ Terminal :: MultiA ( k, ref keys) => {
322+ write ! ( f, "multi_a({}" , k) ?;
323+ for k in keys {
324+ write ! ( f, ",{}" , k) ?;
325+ }
326+ f. write_str ( ")" )
327+ }
315328 _ => unreachable ! ( ) ,
316329 }
317330 }
@@ -368,6 +381,13 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> fmt::Display for Terminal<Pk, Ctx> {
368381 }
369382 f. write_str ( ")" )
370383 }
384+ Terminal :: MultiA ( k, ref keys) => {
385+ write ! ( f, "multi_a({}" , k) ?;
386+ for k in keys {
387+ write ! ( f, ",{}" , k) ?;
388+ }
389+ f. write_str ( ")" )
390+ }
371391 // wrappers
372392 _ => {
373393 if let Some ( ( ch, sub) ) = self . wrap_char ( ) {
@@ -540,7 +560,7 @@ where
540560
541561 Ok ( Terminal :: Thresh ( k, subs?) )
542562 }
543- ( "multi" , n) => {
563+ ( "multi" , n) | ( "multi_a" , n ) => {
544564 if n == 0 {
545565 return Err ( errstr ( "no arguments given" ) ) ;
546566 }
@@ -554,7 +574,12 @@ where
554574 . map ( |sub| expression:: terminal ( sub, Pk :: from_str) )
555575 . collect ( ) ;
556576
557- pks. map ( |pks| Terminal :: Multi ( k, pks) )
577+ if frag_name == "multi" {
578+ pks. map ( |pks| Terminal :: Multi ( k, pks) )
579+ } else {
580+ // must be multi_a
581+ pks. map ( |pks| Terminal :: MultiA ( k, pks) )
582+ }
558583 }
559584 _ => Err ( Error :: Unexpected ( format ! (
560585 "{}({} args) while parsing Miniscript" ,
@@ -745,6 +770,19 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
745770 . push_int ( keys. len ( ) as i64 )
746771 . push_opcode ( opcodes:: all:: OP_CHECKMULTISIG )
747772 }
773+ Terminal :: MultiA ( k, ref keys) => {
774+ debug_assert ! ( Ctx :: is_tap( ) ) ;
775+ // keys must be atleast len 1 here, guaranteed by typing rules
776+ builder = builder. push_ms_key :: < _ , Ctx > ( & keys[ 0 ] ) ;
777+ builder = builder. push_opcode ( opcodes:: all:: OP_CHECKSIG ) ;
778+ for pk in keys. iter ( ) . skip ( 1 ) {
779+ builder = builder. push_ms_key :: < _ , Ctx > ( pk) ;
780+ builder = builder. push_opcode ( opcodes:: all:: OP_CHECKSIGADD ) ;
781+ }
782+ builder
783+ . push_int ( k as i64 )
784+ . push_opcode ( opcodes:: all:: OP_NUMEQUAL )
785+ }
748786 }
749787 }
750788
@@ -799,6 +837,12 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> Terminal<Pk, Ctx> {
799837 + script_num_size ( pks. len ( ) )
800838 + pks. iter ( ) . map ( |pk| Ctx :: pk_len ( pk) ) . sum :: < usize > ( )
801839 }
840+ Terminal :: MultiA ( k, ref pks) => {
841+ script_num_size ( k)
842+ + 1 // NUMEQUAL
843+ + pks. iter ( ) . map ( |pk| Ctx :: pk_len ( pk) ) . sum :: < usize > ( ) // n keys
844+ + pks. len ( ) // n times CHECKSIGADD
845+ }
802846 }
803847 }
804848}
0 commit comments