@@ -3,6 +3,10 @@ use bitcoin::consensus::Decodable;
33use bitcoin:: hashes:: Hash ;
44use bitcoin:: psbt:: Psbt ;
55use bitcoin:: { Network , ScriptBuf , Transaction } ;
6+ use wasm_utxo:: bitgo_psbt:: {
7+ BitGoKeyValue , Musig2PartialSig , Musig2Participants , Musig2PubNonce , ProprietaryKeySubtype ,
8+ BITGO ,
9+ } ;
610
711pub use crate :: node:: { Node , Primitive } ;
812
@@ -39,24 +43,151 @@ fn bip32_derivations_to_nodes(
3943 . collect ( )
4044}
4145
46+ fn musig2_participants_to_node ( participants : & Musig2Participants ) -> Node {
47+ let mut node = Node :: new ( "musig2_participants" , Primitive :: None ) ;
48+ node. add_child ( Node :: new (
49+ "tap_output_key" ,
50+ Primitive :: Buffer ( participants. tap_output_key . serialize ( ) . to_vec ( ) ) ,
51+ ) ) ;
52+ node. add_child ( Node :: new (
53+ "tap_internal_key" ,
54+ Primitive :: Buffer ( participants. tap_internal_key . serialize ( ) . to_vec ( ) ) ,
55+ ) ) ;
56+
57+ let mut participants_node = Node :: new ( "participant_pub_keys" , Primitive :: U64 ( 2 ) ) ;
58+ for ( i, pub_key) in participants. participant_pub_keys . iter ( ) . enumerate ( ) {
59+ let pub_key_vec: Vec < u8 > = pub_key. to_bytes ( ) . to_vec ( ) ;
60+ participants_node. add_child ( Node :: new (
61+ format ! ( "participant_{}" , i) ,
62+ Primitive :: Buffer ( pub_key_vec) ,
63+ ) ) ;
64+ }
65+ node. add_child ( participants_node) ;
66+ node
67+ }
68+
69+ fn musig2_pub_nonce_to_node ( nonce : & Musig2PubNonce ) -> Node {
70+ let mut node = Node :: new ( "musig2_pub_nonce" , Primitive :: None ) ;
71+ node. add_child ( Node :: new (
72+ "participant_pub_key" ,
73+ Primitive :: Buffer ( nonce. participant_pub_key . to_bytes ( ) . to_vec ( ) ) ,
74+ ) ) ;
75+ node. add_child ( Node :: new (
76+ "tap_output_key" ,
77+ Primitive :: Buffer ( nonce. tap_output_key . serialize ( ) . to_vec ( ) ) ,
78+ ) ) ;
79+ node. add_child ( Node :: new (
80+ "pub_nonce" ,
81+ Primitive :: Buffer ( nonce. pub_nonce . serialize ( ) . to_vec ( ) ) ,
82+ ) ) ;
83+ node
84+ }
85+
86+ fn musig2_partial_sig_to_node ( sig : & Musig2PartialSig ) -> Node {
87+ let mut node = Node :: new ( "musig2_partial_sig" , Primitive :: None ) ;
88+ node. add_child ( Node :: new (
89+ "participant_pub_key" ,
90+ Primitive :: Buffer ( sig. participant_pub_key . to_bytes ( ) . to_vec ( ) ) ,
91+ ) ) ;
92+ node. add_child ( Node :: new (
93+ "tap_output_key" ,
94+ Primitive :: Buffer ( sig. tap_output_key . serialize ( ) . to_vec ( ) ) ,
95+ ) ) ;
96+ node. add_child ( Node :: new (
97+ "partial_sig" ,
98+ Primitive :: Buffer ( sig. partial_sig . clone ( ) ) ,
99+ ) ) ;
100+ node
101+ }
102+
103+ fn bitgo_proprietary_to_node ( prop_key : & bitcoin:: psbt:: raw:: ProprietaryKey , v : & [ u8 ] ) -> Node {
104+ // Try to parse as BitGo key-value
105+ let v_vec = v. to_vec ( ) ;
106+ let bitgo_kv_result = BitGoKeyValue :: from_key_value ( prop_key, & v_vec) ;
107+
108+ match bitgo_kv_result {
109+ Ok ( bitgo_kv) => {
110+ // Parse based on subtype
111+ match bitgo_kv. subtype {
112+ ProprietaryKeySubtype :: Musig2ParticipantPubKeys => {
113+ match Musig2Participants :: from_key_value ( & bitgo_kv) {
114+ Ok ( participants) => musig2_participants_to_node ( & participants) ,
115+ Err ( _) => {
116+ // Fall back to raw display
117+ raw_proprietary_to_node ( "musig2_participants_error" , prop_key, v)
118+ }
119+ }
120+ }
121+ ProprietaryKeySubtype :: Musig2PubNonce => {
122+ match Musig2PubNonce :: from_key_value ( & bitgo_kv) {
123+ Ok ( nonce) => musig2_pub_nonce_to_node ( & nonce) ,
124+ Err ( _) => {
125+ // Fall back to raw display
126+ raw_proprietary_to_node ( "musig2_pub_nonce_error" , prop_key, v)
127+ }
128+ }
129+ }
130+ ProprietaryKeySubtype :: Musig2PartialSig => {
131+ match Musig2PartialSig :: from_key_value ( & bitgo_kv) {
132+ Ok ( sig) => musig2_partial_sig_to_node ( & sig) ,
133+ Err ( _) => {
134+ // Fall back to raw display
135+ raw_proprietary_to_node ( "musig2_partial_sig_error" , prop_key, v)
136+ }
137+ }
138+ }
139+ _ => {
140+ // Other BitGo subtypes - show with name
141+ let subtype_name = match bitgo_kv. subtype {
142+ ProprietaryKeySubtype :: ZecConsensusBranchId => "zec_consensus_branch_id" ,
143+ ProprietaryKeySubtype :: PayGoAddressAttestationProof => {
144+ "paygo_address_attestation_proof"
145+ }
146+ ProprietaryKeySubtype :: Bip322Message => "bip322_message" ,
147+ _ => "unknown" ,
148+ } ;
149+ raw_proprietary_to_node ( subtype_name, prop_key, v)
150+ }
151+ }
152+ }
153+ Err ( _) => {
154+ // Not a valid BitGo key-value, show raw
155+ raw_proprietary_to_node ( "unknown" , prop_key, v)
156+ }
157+ }
158+ }
159+
160+ fn raw_proprietary_to_node (
161+ label : & str ,
162+ prop_key : & bitcoin:: psbt:: raw:: ProprietaryKey ,
163+ v : & [ u8 ] ,
164+ ) -> Node {
165+ let mut prop_node = Node :: new ( label, Primitive :: None ) ;
166+ prop_node. add_child ( Node :: new (
167+ "prefix" ,
168+ Primitive :: String ( String :: from_utf8_lossy ( & prop_key. prefix ) . to_string ( ) ) ,
169+ ) ) ;
170+ prop_node. add_child ( Node :: new ( "subtype" , Primitive :: U8 ( prop_key. subtype ) ) ) ;
171+ prop_node. add_child ( Node :: new (
172+ "key_data" ,
173+ Primitive :: Buffer ( prop_key. key . to_vec ( ) ) ,
174+ ) ) ;
175+ prop_node. add_child ( Node :: new ( "value" , Primitive :: Buffer ( v. to_vec ( ) ) ) ) ;
176+ prop_node
177+ }
178+
42179fn proprietary_to_nodes (
43180 proprietary : & std:: collections:: BTreeMap < bitcoin:: psbt:: raw:: ProprietaryKey , Vec < u8 > > ,
44181) -> Vec < Node > {
45182 proprietary
46183 . iter ( )
47184 . map ( |( prop_key, v) | {
48- let mut prop_node = Node :: new ( "key" , Primitive :: None ) ;
49- prop_node. add_child ( Node :: new (
50- "prefix" ,
51- Primitive :: String ( String :: from_utf8_lossy ( & prop_key. prefix ) . to_string ( ) ) ,
52- ) ) ;
53- prop_node. add_child ( Node :: new ( "subtype" , Primitive :: U8 ( prop_key. subtype ) ) ) ;
54- prop_node. add_child ( Node :: new (
55- "key_data" ,
56- Primitive :: Buffer ( prop_key. key . to_vec ( ) ) ,
57- ) ) ;
58- prop_node. add_child ( Node :: new ( "value" , Primitive :: Buffer ( v. to_vec ( ) ) ) ) ;
59- prop_node
185+ // Check if this is a BITGO proprietary key
186+ if prop_key. prefix . as_slice ( ) == BITGO {
187+ bitgo_proprietary_to_node ( prop_key, v)
188+ } else {
189+ raw_proprietary_to_node ( "key" , prop_key, v)
190+ }
60191 } )
61192 . collect ( )
62193}
0 commit comments