33//! This module bridges the Network enum with address codecs, providing
44//! convenient functions to encode/decode addresses using network identifiers.
55
6+ use super :: bech32:: is_p2mr;
67use super :: {
78 from_output_script, to_output_script_try_codecs, AddressCodec , AddressError , Result , ScriptBuf ,
89 BITCOIN , BITCOIN_BECH32 , BITCOIN_CASH , BITCOIN_CASH_CASHADDR , BITCOIN_CASH_TESTNET ,
@@ -76,6 +77,7 @@ impl AddressFormat {
7677pub struct OutputScriptSupport {
7778 pub segwit : bool ,
7879 pub taproot : bool ,
80+ pub p2mr : bool ,
7981}
8082
8183impl OutputScriptSupport {
@@ -102,6 +104,15 @@ impl OutputScriptSupport {
102104 Ok ( ( ) )
103105 }
104106
107+ pub ( crate ) fn assert_p2mr ( & self ) -> Result < ( ) > {
108+ if !self . p2mr {
109+ return Err ( AddressError :: UnsupportedScriptType (
110+ "Network does not support P2MR" . to_string ( ) ,
111+ ) ) ;
112+ }
113+ Ok ( ( ) )
114+ }
115+
105116 pub fn assert_support ( & self , script : & Script ) -> Result < ( ) > {
106117 match script. witness_version ( ) {
107118 None => {
@@ -113,6 +124,9 @@ impl OutputScriptSupport {
113124 Some ( WitnessVersion :: V1 ) => {
114125 self . assert_taproot ( ) ?;
115126 }
127+ Some ( WitnessVersion :: V2 ) => {
128+ self . assert_p2mr ( ) ?;
129+ }
116130 _ => {
117131 return Err ( AddressError :: UnsupportedScriptType (
118132 "Unsupported witness version" . to_string ( ) ,
@@ -170,7 +184,16 @@ impl Network {
170184 // - https://github.com/litecoin-project/litecoin/blob/v0.21.4/src/script/interpreter.h#L129-L131
171185 let taproot = segwit && matches ! ( self . mainnet( ) , Network :: Bitcoin ) ;
172186
173- OutputScriptSupport { segwit, taproot }
187+ // P2MR (BIP-360) support:
188+ // Enabled on all Bitcoin networks (mainnet + testnets) for address encoding.
189+ // Backend activation is controlled separately.
190+ let p2mr = matches ! ( self . mainnet( ) , Network :: Bitcoin ) ;
191+
192+ OutputScriptSupport {
193+ segwit,
194+ taproot,
195+ p2mr,
196+ }
174197 }
175198}
176199
@@ -182,12 +205,13 @@ fn get_encode_codec(
182205) -> Result < & ' static dyn AddressCodec > {
183206 network. output_script_support ( ) . assert_support ( script) ?;
184207
185- let is_witness = script. is_p2wpkh ( ) || script. is_p2wsh ( ) || script. is_p2tr ( ) ;
208+ let is_witness = script. is_p2wpkh ( ) || script. is_p2wsh ( ) || script. is_p2tr ( ) || is_p2mr ( script ) ;
186209 let is_legacy = script. is_p2pkh ( ) || script. is_p2sh ( ) ;
187210
188211 if !is_witness && !is_legacy {
189212 return Err ( AddressError :: UnsupportedScriptType (
190- "Script is not a standard address type (P2PKH, P2SH, P2WPKH, P2WSH, P2TR)" . to_string ( ) ,
213+ "Script is not a standard address type (P2PKH, P2SH, P2WPKH, P2WSH, P2TR, P2MR)"
214+ . to_string ( ) ,
191215 ) ) ;
192216 }
193217
@@ -554,12 +578,14 @@ mod tests {
554578 let support_none = OutputScriptSupport {
555579 segwit : false ,
556580 taproot : false ,
581+ p2mr : false ,
557582 } ;
558583 assert ! ( support_none. assert_legacy( ) . is_ok( ) ) ;
559584
560585 let support_all = OutputScriptSupport {
561586 segwit : true ,
562587 taproot : true ,
588+ p2mr : false ,
563589 } ;
564590 assert ! ( support_all. assert_legacy( ) . is_ok( ) ) ;
565591 }
@@ -570,13 +596,15 @@ mod tests {
570596 let support_segwit = OutputScriptSupport {
571597 segwit : true ,
572598 taproot : false ,
599+ p2mr : false ,
573600 } ;
574601 assert ! ( support_segwit. assert_segwit( ) . is_ok( ) ) ;
575602
576603 // Should fail when segwit is not supported
577604 let no_support = OutputScriptSupport {
578605 segwit : false ,
579606 taproot : false ,
607+ p2mr : false ,
580608 } ;
581609 let result = no_support. assert_segwit ( ) ;
582610 assert ! ( result. is_err( ) ) ;
@@ -592,13 +620,15 @@ mod tests {
592620 let support_taproot = OutputScriptSupport {
593621 segwit : true ,
594622 taproot : true ,
623+ p2mr : false ,
595624 } ;
596625 assert ! ( support_taproot. assert_taproot( ) . is_ok( ) ) ;
597626
598627 // Should fail when taproot is not supported
599628 let no_support = OutputScriptSupport {
600629 segwit : true ,
601630 taproot : false ,
631+ p2mr : false ,
602632 } ;
603633 let result = no_support. assert_taproot ( ) ;
604634 assert ! ( result. is_err( ) ) ;
@@ -619,6 +649,7 @@ mod tests {
619649 let no_support = OutputScriptSupport {
620650 segwit : false ,
621651 taproot : false ,
652+ p2mr : false ,
622653 } ;
623654 assert ! ( no_support. assert_support( & p2pkh_script) . is_ok( ) ) ;
624655
@@ -640,13 +671,15 @@ mod tests {
640671 let support_segwit = OutputScriptSupport {
641672 segwit : true ,
642673 taproot : false ,
674+ p2mr : false ,
643675 } ;
644676 assert ! ( support_segwit. assert_support( & p2wpkh_script) . is_ok( ) ) ;
645677
646678 // Should fail without segwit support
647679 let no_support = OutputScriptSupport {
648680 segwit : false ,
649681 taproot : false ,
682+ p2mr : false ,
650683 } ;
651684 let result = no_support. assert_support ( & p2wpkh_script) ;
652685 assert ! ( result. is_err( ) ) ;
@@ -685,13 +718,15 @@ mod tests {
685718 let support_taproot = OutputScriptSupport {
686719 segwit : true ,
687720 taproot : true ,
721+ p2mr : false ,
688722 } ;
689723 assert ! ( support_taproot. assert_support( & p2tr_script) . is_ok( ) ) ;
690724
691725 // Should fail without taproot support (but with segwit)
692726 let no_taproot = OutputScriptSupport {
693727 segwit : true ,
694728 taproot : false ,
729+ p2mr : false ,
695730 } ;
696731 let result = no_taproot. assert_support ( & p2tr_script) ;
697732 assert ! ( result. is_err( ) ) ;
@@ -704,6 +739,7 @@ mod tests {
704739 let no_support = OutputScriptSupport {
705740 segwit : false ,
706741 taproot : false ,
742+ p2mr : false ,
707743 } ;
708744 let result = no_support. assert_support ( & p2tr_script) ;
709745 assert ! ( result. is_err( ) ) ;
0 commit comments