Skip to content

Commit 85a33c5

Browse files
committed
bindings: refactored x-only public key to be uniffi::Object
1 parent 9efcc03 commit 85a33c5

File tree

2 files changed

+41
-50
lines changed

2 files changed

+41
-50
lines changed

lwk_bindings/src/simplicity.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ pub fn simplicity_load_program(
150150
#[uniffi::export]
151151
pub fn simplicity_create_p2tr_address(
152152
program: &SimplicityProgram,
153-
internal_key: XOnlyPublicKey,
153+
internal_key: &XOnlyPublicKey,
154154
network: &Network,
155155
) -> Result<Arc<Address>, LwkError> {
156156
let x_only_key = internal_key.to_simplicityhl()?;
@@ -173,7 +173,7 @@ pub fn simplicity_create_p2tr_address(
173173
#[uniffi::export]
174174
pub fn simplicity_control_block(
175175
program: &SimplicityProgram,
176-
internal_key: XOnlyPublicKey,
176+
internal_key: &XOnlyPublicKey,
177177
) -> Result<Hex, LwkError> {
178178
let x_only_key = internal_key.to_simplicityhl()?;
179179

@@ -200,7 +200,7 @@ pub fn simplicity_control_block(
200200
pub fn simplicity_get_sighash_all(
201201
tx: &Transaction,
202202
program: &SimplicityProgram,
203-
program_public_key: XOnlyPublicKey,
203+
program_public_key: &XOnlyPublicKey,
204204
utxos: Vec<Arc<TxOut>>,
205205
input_index: u32,
206206
network: &Network,
@@ -249,7 +249,7 @@ pub fn simplicity_get_sighash_all(
249249
pub fn simplicity_finalize_transaction(
250250
tx: &Transaction,
251251
program: &SimplicityProgram,
252-
program_public_key: XOnlyPublicKey,
252+
program_public_key: &XOnlyPublicKey,
253253
utxos: Vec<Arc<TxOut>>,
254254
input_index: u32,
255255
witness_values: &SimplicityWitnessValues,
@@ -359,7 +359,7 @@ pub fn simplicity_create_p2pk_signature(
359359
pub fn simplicity_derive_xonly_pubkey(
360360
signer: &crate::Signer,
361361
derivation_path: String,
362-
) -> Result<XOnlyPublicKey, LwkError> {
362+
) -> Result<Arc<XOnlyPublicKey>, LwkError> {
363363
let path = DerivationPath::from_str(&derivation_path).map_err(|e| LwkError::Generic {
364364
msg: format!("Invalid derivation path: {e}"),
365365
})?;

lwk_bindings/src/types/xonly_public_key.rs

Lines changed: 36 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,48 @@
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)]
88
pub struct XOnlyPublicKey {
99
inner: elements::bitcoin::XOnlyPublicKey,
1010
}
1111

12+
#[uniffi::export]
1213
impl 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)]
111107
mod 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

Comments
 (0)