1- use std:: { fmt:: Display , str:: FromStr } ;
1+ use std:: { fmt:: Display , str:: FromStr , sync :: Arc } ;
22
3- use crate :: { LwkError , UniffiCustomTypeConverter } ;
3+ use crate :: LwkError ;
44
55/// An x-only public key, used for verification of Taproot signatures
66/// and serialized according to BIP-340.
7- #[ derive( PartialEq , Eq , Debug , Clone , Copy ) ]
7+ #[ derive( uniffi :: Object , PartialEq , Eq , Debug , Clone , Copy ) ]
88pub struct XOnlyPublicKey {
99 inner : elements:: bitcoin:: XOnlyPublicKey ,
1010}
1111
12+ #[ uniffi:: export]
1213impl XOnlyPublicKey {
13- /// Create from a keypair, returning the x-only public key.
14- #[ must_use]
15- pub fn from_keypair ( keypair : & elements:: bitcoin:: secp256k1:: Keypair ) -> Self {
16- let ( xonly, _parity) = keypair. x_only_public_key ( ) ;
17- Self :: from ( xonly)
14+ /// Create from a hex string (64 hex characters = 32 bytes).
15+ #[ uniffi:: constructor]
16+ pub fn new ( hex : & str ) -> Result < Arc < Self > , LwkError > {
17+ Ok ( Arc :: new ( Self :: from_str ( hex) ?) )
1818 }
1919
2020 /// Create from raw bytes (32 bytes).
21- pub fn from_slice ( bytes : & [ u8 ] ) -> Result < Self , LwkError > {
21+ #[ uniffi:: constructor]
22+ pub fn from_slice ( bytes : & [ u8 ] ) -> Result < Arc < Self > , LwkError > {
2223 let inner = elements:: bitcoin:: XOnlyPublicKey :: from_slice ( bytes) . map_err ( |e| {
2324 LwkError :: Generic {
2425 msg : format ! ( "Invalid x-only public key: {e}" ) ,
2526 }
2627 } ) ?;
28+ Ok ( Arc :: new ( Self { inner } ) )
29+ }
2730
28- Ok ( Self { inner } )
31+ /// Serialize to 32 bytes.
32+ pub fn bytes ( & self ) -> Vec < u8 > {
33+ self . inner . serialize ( ) . to_vec ( )
2934 }
35+ }
3036
31- /// Deserialize from 32 bytes. Alias for `from_slice`.
32- pub fn deserialize ( bytes : & [ u8 ; 32 ] ) -> Result < Self , LwkError > {
33- Self :: from_slice ( bytes)
37+ impl XOnlyPublicKey {
38+ /// Create from a keypair, returning the x-only public key
39+ #[ must_use]
40+ pub fn from_keypair ( keypair : & elements:: bitcoin:: secp256k1:: Keypair ) -> Arc < Self > {
41+ let ( xonly, _parity) = keypair. x_only_public_key ( ) ;
42+ Arc :: new ( Self :: from ( xonly) )
3443 }
3544
36- /// Serialize to 32 bytes.
45+ /// Serialize to 32 bytes
3746 #[ must_use]
3847 pub fn serialize ( & self ) -> [ u8 ; 32 ] {
3948 self . inner . serialize ( )
@@ -94,40 +103,22 @@ impl Display for XOnlyPublicKey {
94103 }
95104}
96105
97- uniffi:: custom_type!( XOnlyPublicKey , String ) ;
98- impl UniffiCustomTypeConverter for XOnlyPublicKey {
99- type Builtin = String ;
100-
101- fn into_custom ( val : Self :: Builtin ) -> uniffi:: Result < Self > {
102- Ok ( Self :: from_str ( & val) ?)
103- }
104-
105- fn from_custom ( obj : Self ) -> Self :: Builtin {
106- obj. to_string ( )
107- }
108- }
109-
110106#[ cfg( test) ]
111107mod tests {
112108 use std:: str:: FromStr ;
113109
114110 use elements:: bitcoin:: secp256k1:: { Keypair , Secp256k1 , SecretKey } ;
115111
116112 use super :: XOnlyPublicKey ;
117- use crate :: UniffiCustomTypeConverter ;
118113
119114 #[ test]
120115 fn xonly_public_key_roundtrip ( ) {
121116 let hex = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" ;
122- let key = XOnlyPublicKey :: from_str ( hex) . unwrap ( ) ;
117+ let key = XOnlyPublicKey :: new ( hex) . unwrap ( ) ;
123118
124- assert_eq ! (
125- <XOnlyPublicKey as UniffiCustomTypeConverter >:: into_custom(
126- UniffiCustomTypeConverter :: from_custom( key)
127- )
128- . unwrap( ) ,
129- key
130- ) ;
119+ let as_string = key. to_string ( ) ;
120+ let key2 = XOnlyPublicKey :: new ( & as_string) . unwrap ( ) ;
121+ assert_eq ! ( * key, * key2) ;
131122 }
132123
133124 #[ test]
@@ -143,14 +134,14 @@ mod tests {
143134 }
144135
145136 #[ test]
146- fn xonly_public_key_serialize_deserialize_roundtrip ( ) {
137+ fn xonly_public_key_bytes_roundtrip ( ) {
147138 let hex = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" ;
148139 let key = XOnlyPublicKey :: from_str ( hex) . unwrap ( ) ;
149140
150- let serialized = key. serialize ( ) ;
151- let deserialized = XOnlyPublicKey :: deserialize ( & serialized) . unwrap ( ) ;
141+ let serialized = key. bytes ( ) ;
142+ let deserialized = XOnlyPublicKey :: from_slice ( & serialized) . unwrap ( ) ;
152143
153- assert_eq ! ( key, deserialized) ;
144+ assert_eq ! ( key, * deserialized) ;
154145 }
155146
156147 #[ test]
@@ -164,16 +155,16 @@ mod tests {
164155 }
165156
166157 #[ test]
167- fn xonly_public_key_from_str_invalid ( ) {
158+ fn xonly_public_key_new_invalid ( ) {
168159 // Too short
169- assert ! ( XOnlyPublicKey :: from_str ( "aabb" ) . is_err( ) ) ;
160+ assert ! ( XOnlyPublicKey :: new ( "aabb" ) . is_err( ) ) ;
170161 // Too long
171- assert ! ( XOnlyPublicKey :: from_str (
162+ assert ! ( XOnlyPublicKey :: new (
172163 "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179800"
173164 )
174165 . is_err( ) ) ;
175166 // Invalid hex
176- assert ! ( XOnlyPublicKey :: from_str (
167+ assert ! ( XOnlyPublicKey :: new (
177168 "xx79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817"
178169 )
179170 . is_err( ) ) ;
@@ -182,7 +173,7 @@ mod tests {
182173 #[ test]
183174 fn xonly_public_key_display ( ) {
184175 let hex = "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798" ;
185- let key = XOnlyPublicKey :: from_str ( hex) . unwrap ( ) ;
176+ let key = XOnlyPublicKey :: new ( hex) . unwrap ( ) ;
186177
187178 assert_eq ! ( key. to_string( ) , hex) ;
188179 }
0 commit comments