Skip to content

Commit d23ee9a

Browse files
committed
bindings: add missing constructors, utils, and lock time type
1 parent bce5408 commit d23ee9a

File tree

8 files changed

+289
-10
lines changed

8 files changed

+289
-10
lines changed

lwk_bindings/src/blockdata/out_point.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ impl OutPoint {
4545
Ok(Arc::new(Self { inner }))
4646
}
4747

48+
/// Create an OutPoint from a transaction id and output index.
49+
#[uniffi::constructor]
50+
pub fn from_parts(txid: &Txid, vout: u32) -> Arc<Self> {
51+
Arc::new(Self {
52+
inner: elements::OutPoint::new(txid.into(), vout),
53+
})
54+
}
55+
4856
/// Return the transaction identifier.
4957
pub fn txid(&self) -> Arc<Txid> {
5058
Arc::new(self.inner.txid.into())
@@ -58,7 +66,7 @@ impl OutPoint {
5866

5967
#[cfg(test)]
6068
mod tests {
61-
use crate::OutPoint;
69+
use crate::{OutPoint, Txid};
6270
use std::str::FromStr;
6371

6472
#[test]
@@ -82,4 +90,20 @@ mod tests {
8290

8391
assert_eq!(expected_vout, out_point.vout());
8492
}
93+
94+
#[test]
95+
fn test_out_point_from_parts() {
96+
let txid_hex = "0000000000000000000000000000000000000000000000000000000000000001";
97+
let txid = Txid::new(&txid_hex.parse().unwrap()).unwrap();
98+
let vout = 5;
99+
100+
let out_point = OutPoint::from_parts(&txid, vout);
101+
102+
assert_eq!(out_point.txid().to_string(), txid_hex);
103+
assert_eq!(out_point.vout(), vout);
104+
assert_eq!(
105+
out_point.to_string(),
106+
format!("[elements]{txid_hex}:{vout}")
107+
);
108+
}
85109
}

lwk_bindings/src/blockdata/script.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,22 @@ impl Script {
4646
Ok(Arc::new(Self { inner }))
4747
}
4848

49+
/// Create an empty script (for fee outputs).
50+
#[uniffi::constructor]
51+
pub fn empty() -> Arc<Self> {
52+
Arc::new(Self {
53+
inner: elements::Script::new(),
54+
})
55+
}
56+
57+
/// Create an OP_RETURN script (for burn outputs).
58+
#[uniffi::constructor]
59+
pub fn new_op_return(data: Vec<u8>) -> Arc<Self> {
60+
Arc::new(Self {
61+
inner: elements::Script::new_op_return(&data),
62+
})
63+
}
64+
4965
/// Return the consensus encoded bytes of the script.
5066
pub fn bytes(&self) -> Vec<u8> {
5167
self.inner.as_bytes().to_vec()
@@ -99,4 +115,21 @@ mod tests {
99115
let burn = Script::new(&"6a".parse().unwrap()).unwrap();
100116
assert!(burn.is_provably_unspendable());
101117
}
118+
119+
#[test]
120+
fn test_script_empty() {
121+
let script = Script::empty();
122+
assert!(script.bytes().is_empty());
123+
assert_eq!(script.to_string(), "");
124+
assert_eq!(script.to_asm(), "");
125+
}
126+
127+
#[test]
128+
fn test_script_op_return() {
129+
let data = b"burn".to_vec();
130+
let script = Script::new_op_return(data.clone());
131+
// OP_RETURN + OP_PUSHBYTES_4 + "burn"
132+
assert!(script.is_provably_unspendable());
133+
assert!(script.to_asm().starts_with("OP_RETURN"));
134+
}
102135
}

lwk_bindings/src/blockdata/transaction.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use elements::{
44
hex::ToHex,
55
pset::serialize::{Deserialize, Serialize},
66
};
7-
use lwk_wollet::WalletTx;
7+
use lwk_wollet::{WalletTx, EC};
88

99
use crate::{
1010
types::{AssetId, Hex},
@@ -103,6 +103,15 @@ impl Transaction {
103103
.map(|i| Arc::new(i.clone().into()))
104104
.collect()
105105
}
106+
107+
/// Verify transaction amount proofs against UTXOs.
108+
///
109+
/// See [`elements::Transaction::verify_tx_amt_proofs`].
110+
pub fn verify_tx_amt_proofs(&self, utxos: Vec<Arc<TxOut>>) -> Result<(), LwkError> {
111+
let utxos_inner: Vec<elements::TxOut> = utxos.iter().map(|u| u.as_ref().into()).collect();
112+
self.inner.verify_tx_amt_proofs(&EC, &utxos_inner)?;
113+
Ok(())
114+
}
106115
}
107116

108117
#[cfg(test)]

lwk_bindings/src/blockdata/tx_out_secrets.rs

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
33
use std::sync::Arc;
44

5-
use elements::confidential::{AssetBlindingFactor, ValueBlindingFactor};
65
use elements::secp256k1_zkp::{Generator, PedersenCommitment, Tag};
76
use lwk_wollet::EC;
87

9-
use crate::types::{AssetId, Hex};
8+
use crate::types::{
9+
AssetBlindingFactor as BindingsAssetBlindingFactor, AssetId, Hex,
10+
ValueBlindingFactor as BindingsValueBlindingFactor,
11+
};
1012

1113
/// Contains unblinded information such as the asset and the value of a transaction output
1214
#[derive(uniffi::Object, PartialEq, Eq, Debug)]
@@ -28,15 +30,33 @@ impl From<&TxOutSecrets> for elements::TxOutSecrets {
2830

2931
#[uniffi::export]
3032
impl TxOutSecrets {
33+
/// Create TxOutSecrets with explicit blinding factors.
34+
#[uniffi::constructor]
35+
pub fn new(
36+
asset_id: AssetId,
37+
asset_bf: &BindingsAssetBlindingFactor,
38+
value: u64,
39+
value_bf: &BindingsValueBlindingFactor,
40+
) -> Arc<Self> {
41+
Arc::new(Self {
42+
inner: elements::TxOutSecrets::new(
43+
asset_id.into(),
44+
asset_bf.into(),
45+
value,
46+
value_bf.into(),
47+
),
48+
})
49+
}
50+
3151
/// Create TxOutSecrets from explicit (unblinded) values.
3252
#[uniffi::constructor]
3353
pub fn from_explicit(asset_id: AssetId, value: u64) -> Arc<Self> {
3454
Arc::new(Self {
3555
inner: elements::TxOutSecrets::new(
3656
asset_id.into(),
37-
AssetBlindingFactor::zero(),
57+
elements::confidential::AssetBlindingFactor::zero(),
3858
value,
39-
ValueBlindingFactor::zero(),
59+
elements::confidential::ValueBlindingFactor::zero(),
4060
),
4161
})
4262
}
@@ -71,8 +91,8 @@ impl TxOutSecrets {
7191

7292
/// Return true if the output is explicit (no blinding factors).
7393
pub fn is_explicit(&self) -> bool {
74-
self.inner.asset_bf == AssetBlindingFactor::zero()
75-
&& self.inner.value_bf == ValueBlindingFactor::zero()
94+
self.inner.asset_bf == elements::confidential::AssetBlindingFactor::zero()
95+
&& self.inner.value_bf == elements::confidential::ValueBlindingFactor::zero()
7696
}
7797

7898
/// Get the asset commitment
@@ -118,10 +138,14 @@ impl TxOutSecrets {
118138

119139
#[cfg(test)]
120140
mod tests {
141+
use crate::UniffiCustomTypeConverter;
142+
use crate::{types, TxOutSecrets};
143+
144+
use std::str::FromStr;
145+
121146
use elements::confidential::{AssetBlindingFactor, ValueBlindingFactor};
122147
use elements::hex::FromHex;
123148
use elements::AssetId;
124-
use std::str::FromStr;
125149

126150
#[test]
127151
fn tx_out_secrets() {
@@ -164,4 +188,23 @@ mod tests {
164188
assert_eq!(txoutsecrets_blinded.asset_commitment().to_string(), ac_hex);
165189
assert_eq!(txoutsecrets_blinded.value_commitment().to_string(), vc_hex);
166190
}
191+
192+
#[test]
193+
fn test_tx_out_secrets_new_with_blinding() {
194+
let asset_hex = "1111111111111111111111111111111111111111111111111111111111111111";
195+
let abf_hex = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
196+
let vbf_hex = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
197+
198+
let asset_id = types::AssetId::into_custom(asset_hex.to_string()).unwrap();
199+
let asset_bf = types::AssetBlindingFactor::from_hex(abf_hex).unwrap();
200+
let value_bf = types::ValueBlindingFactor::from_hex(vbf_hex).unwrap();
201+
202+
let secrets = TxOutSecrets::new(asset_id, &asset_bf, 1000, &value_bf);
203+
204+
assert!(!secrets.is_explicit());
205+
assert_eq!(secrets.asset().to_string(), asset_hex);
206+
assert_eq!(secrets.asset_bf().to_string(), abf_hex);
207+
assert_eq!(secrets.value(), 1000);
208+
assert_eq!(secrets.value_bf().to_string(), vbf_hex);
209+
}
167210
}

lwk_bindings/src/error.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,22 @@ impl From<elements::bitcoin::bip32::Error> for LwkError {
209209
}
210210
}
211211

212+
impl From<elements::locktime::Error> for LwkError {
213+
fn from(value: elements::locktime::Error) -> Self {
214+
LwkError::Generic {
215+
msg: format!("{value:?}"),
216+
}
217+
}
218+
}
219+
220+
impl From<elements::VerificationError> for LwkError {
221+
fn from(value: elements::VerificationError) -> Self {
222+
LwkError::Generic {
223+
msg: format!("{value:?}"),
224+
}
225+
}
226+
}
227+
212228
#[cfg(feature = "simplicity")]
213229
impl From<lwk_simplicity_options::error::ProgramError> for LwkError {
214230
fn from(value: lwk_simplicity_options::error::ProgramError) -> Self {

lwk_bindings/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ pub use blockdata::wallet_tx_out::WalletTxOut;
7171
pub use crate::contract::Contract;
7272
pub use crate::signer::{Bip, Signer};
7373
pub use crate::types::{
74-
AssetBlindingFactor, Keypair, PublicKey, TxSequence, ValueBlindingFactor, XOnlyPublicKey,
74+
AssetBlindingFactor, Keypair, LockTime, PublicKey, TxSequence, ValueBlindingFactor,
75+
XOnlyPublicKey,
7576
};
7677
pub use crate::wollet::Wollet;
7778
pub use chain::Chain;

0 commit comments

Comments
 (0)