bdkffi/
bitcoin.rs

1use crate::error::{
2    AddressParseError, Bip32Error, ExtractTxError, FeeRateError, FromScriptError, HashParseError,
3    PsbtError, PsbtParseError, TransactionError,
4};
5use crate::error::{ParseAmountError, PsbtFinalizeError};
6use crate::keys::DerivationPath;
7
8use crate::{impl_from_core_type, impl_hash_like, impl_into_core_type};
9use bdk_wallet::bitcoin::address::NetworkChecked;
10use bdk_wallet::bitcoin::address::NetworkUnchecked;
11use bdk_wallet::bitcoin::address::{Address as BdkAddress, AddressData as BdkAddressData};
12use bdk_wallet::bitcoin::bip32::ChildNumber as BdkChildNumber;
13use bdk_wallet::bitcoin::blockdata::block::Block as BdkBlock;
14use bdk_wallet::bitcoin::blockdata::block::Header as BdkHeader;
15use bdk_wallet::bitcoin::consensus::encode::deserialize;
16use bdk_wallet::bitcoin::consensus::encode::serialize;
17use bdk_wallet::bitcoin::consensus::Decodable;
18use bdk_wallet::bitcoin::hashes::sha256::Hash as BitcoinSha256Hash;
19use bdk_wallet::bitcoin::hashes::sha256d::Hash as BitcoinDoubleSha256Hash;
20use bdk_wallet::bitcoin::io::Cursor;
21use bdk_wallet::bitcoin::psbt::Input as BdkInput;
22use bdk_wallet::bitcoin::psbt::Output as BdkOutput;
23use bdk_wallet::bitcoin::secp256k1::Secp256k1;
24use bdk_wallet::bitcoin::taproot::LeafNode as BdkLeafNode;
25use bdk_wallet::bitcoin::taproot::NodeInfo as BdkNodeInfo;
26use bdk_wallet::bitcoin::taproot::TapTree as BdkTapTree;
27use bdk_wallet::bitcoin::Amount as BdkAmount;
28use bdk_wallet::bitcoin::BlockHash as BitcoinBlockHash;
29use bdk_wallet::bitcoin::FeeRate as BdkFeeRate;
30use bdk_wallet::bitcoin::OutPoint as BdkOutPoint;
31use bdk_wallet::bitcoin::Psbt as BdkPsbt;
32use bdk_wallet::bitcoin::ScriptBuf as BdkScriptBuf;
33use bdk_wallet::bitcoin::Transaction as BdkTransaction;
34use bdk_wallet::bitcoin::TxIn as BdkTxIn;
35use bdk_wallet::bitcoin::TxOut as BdkTxOut;
36use bdk_wallet::bitcoin::Txid as BitcoinTxid;
37use bdk_wallet::bitcoin::Weight;
38use bdk_wallet::bitcoin::Wtxid as BitcoinWtxid;
39use bdk_wallet::miniscript::psbt::PsbtExt;
40use bdk_wallet::serde_json;
41
42use std::collections::HashMap;
43use std::convert::TryFrom;
44use std::fmt::Display;
45use std::fs::File;
46use std::io::{BufReader, BufWriter};
47use std::ops::Deref;
48use std::str::FromStr;
49use std::sync::{Arc, Mutex};
50
51pub type DescriptorType = bdk_wallet::miniscript::descriptor::DescriptorType;
52pub type Network = bdk_wallet::bitcoin::Network;
53pub(crate) type NetworkKind = bdk_wallet::bitcoin::NetworkKind;
54
55/// What kind of network we are on.
56#[uniffi::remote(Enum)]
57pub enum NetworkKind {
58    /// The Bitcoin mainnet network.
59    Main,
60    /// Some kind of testnet network.
61    Test,
62}
63
64/// A reference to an unspent output by TXID and output index.
65#[derive(Debug, Clone, Eq, PartialEq, std::hash::Hash, uniffi:: Record)]
66pub struct OutPoint {
67    /// The transaction.
68    pub txid: Arc<Txid>,
69    /// The index of the output in the transaction.
70    pub vout: u32,
71}
72
73impl From<&BdkOutPoint> for OutPoint {
74    fn from(outpoint: &BdkOutPoint) -> Self {
75        OutPoint {
76            txid: Arc::new(Txid(outpoint.txid)),
77            vout: outpoint.vout,
78        }
79    }
80}
81
82impl From<BdkOutPoint> for OutPoint {
83    fn from(value: BdkOutPoint) -> Self {
84        Self {
85            txid: Arc::new(Txid(value.txid)),
86            vout: value.vout,
87        }
88    }
89}
90
91impl From<OutPoint> for BdkOutPoint {
92    fn from(outpoint: OutPoint) -> Self {
93        BdkOutPoint {
94            txid: BitcoinTxid::from_raw_hash(outpoint.txid.0.to_raw_hash()),
95            vout: outpoint.vout,
96        }
97    }
98}
99
100/// The cryptocurrency network to act on.
101///
102/// This is an exhaustive enum, meaning that we cannot add any future networks without defining a
103/// new, incompatible version of this type. If you are using this type directly and wish to support
104/// the new network, this will be a breaking change to your APIs and likely require changes in your
105/// code.
106///
107/// If you are concerned about forward compatibility, consider using T: Into<Params> instead of this
108/// type as a parameter to functions in your public API, or directly using the Params type.
109#[uniffi::remote(Enum)]
110pub enum Network {
111    Bitcoin,
112    Testnet,
113    Testnet4,
114    Signet,
115    Regtest,
116}
117
118/// An [`OutPoint`] used as a key in a hash map.
119///
120/// Due to limitations in generating the foreign language bindings, we cannot use [`OutPoint`] as a
121/// key for hash maps.
122#[derive(Debug, PartialEq, Eq, std::hash::Hash, uniffi::Object)]
123#[uniffi::export(Debug, Eq, Hash)]
124pub struct HashableOutPoint(pub(crate) OutPoint);
125
126#[uniffi::export]
127impl HashableOutPoint {
128    /// Create a key for a key-value store from an [`OutPoint`]
129    #[uniffi::constructor]
130    pub fn new(outpoint: OutPoint) -> Self {
131        Self(outpoint)
132    }
133
134    /// Get the internal [`OutPoint`]
135    pub fn outpoint(&self) -> OutPoint {
136        self.0.clone()
137    }
138}
139
140/// Represents fee rate.
141///
142/// This is an integer type representing fee rate in sat/kwu. It provides protection against mixing
143/// up the types as well as basic formatting features.
144#[derive(Clone, Debug, uniffi::Object)]
145#[uniffi::export(Display)]
146pub struct FeeRate(pub(crate) BdkFeeRate);
147
148#[uniffi::export]
149impl FeeRate {
150    /// Constructs `FeeRate` from satoshis per virtual bytes.
151    #[uniffi::constructor]
152    pub fn from_sat_per_vb(sat_vb: u64) -> Result<Self, FeeRateError> {
153        let fee_rate: Option<BdkFeeRate> = BdkFeeRate::from_sat_per_vb(sat_vb);
154        match fee_rate {
155            Some(fee_rate) => Ok(FeeRate(fee_rate)),
156            None => Err(FeeRateError::ArithmeticOverflow),
157        }
158    }
159
160    /// Constructs `FeeRate` from satoshis per 1000 weight units.
161    #[uniffi::constructor]
162    pub fn from_sat_per_kwu(sat_kwu: u64) -> Self {
163        FeeRate(BdkFeeRate::from_sat_per_kwu(sat_kwu))
164    }
165
166    /// Converts to sat/vB rounding up.
167    pub fn to_sat_per_vb_ceil(&self) -> u64 {
168        self.0.to_sat_per_vb_ceil()
169    }
170
171    /// Converts to sat/vB rounding down.
172    pub fn to_sat_per_vb_floor(&self) -> u64 {
173        self.0.to_sat_per_vb_floor()
174    }
175
176    /// Returns raw fee rate.
177    pub fn to_sat_per_kwu(&self) -> u64 {
178        self.0.to_sat_per_kwu()
179    }
180
181    /// Calculates fee in satoshis by multiplying this fee rate by weight, in virtual bytes, returning `None` if overflow occurred.
182    ///
183    /// This is equivalent to converting vb to weight using Weight::from_vb and then calling Self::fee_wu(weight).
184    pub fn fee_vb(&self, vb: u64) -> Option<Arc<Amount>> {
185        let rust_amount: BdkAmount = self.0.fee_vb(vb)?;
186        let amount: Amount = rust_amount.into();
187        Some(Arc::new(amount))
188
189        // The whole code above should be replaceable by the following line:
190        // self.0.fee_vb(vb).map(Arc::new(Amount::from))
191        // But in practice you get uniffi compilation errors on it. Not sure what is going on with it,
192        // but the code we use works just as well.
193    }
194
195    /// Calculates fee by multiplying this fee rate by weight, in weight units, returning `None` if overflow occurred.
196    ///
197    /// This is equivalent to Self::checked_mul_by_weight().
198    pub fn fee_wu(&self, wu: u64) -> Option<Arc<Amount>> {
199        let weight: Weight = Weight::from_wu(wu);
200        let rust_amount: BdkAmount = self.0.fee_wu(weight)?;
201        let amount: Amount = rust_amount.into();
202        Some(Arc::new(amount))
203    }
204}
205
206impl Display for FeeRate {
207    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
208        write!(f, "{:#}", self.0)
209    }
210}
211
212impl_from_core_type!(BdkFeeRate, FeeRate);
213impl_into_core_type!(FeeRate, BdkFeeRate);
214
215/// The Amount type can be used to express Bitcoin amounts that support arithmetic and conversion
216/// to various denominations. The operations that Amount implements will panic when overflow or
217/// underflow occurs. Also note that since the internal representation of amounts is unsigned,
218/// subtracting below zero is considered an underflow and will cause a panic.
219#[derive(Debug, Clone, PartialEq, Eq, uniffi::Object)]
220pub struct Amount(pub(crate) BdkAmount);
221
222#[uniffi::export]
223impl Amount {
224    /// Create an Amount with satoshi precision and the given number of satoshis.
225    #[uniffi::constructor]
226    pub fn from_sat(satoshi: u64) -> Self {
227        Amount(BdkAmount::from_sat(satoshi))
228    }
229
230    /// Convert from a value expressing bitcoins to an Amount.
231    #[uniffi::constructor]
232    pub fn from_btc(btc: f64) -> Result<Self, ParseAmountError> {
233        let bitcoin_amount = BdkAmount::from_btc(btc).map_err(ParseAmountError::from)?;
234        Ok(Amount(bitcoin_amount))
235    }
236
237    /// Get the number of satoshis in this Amount.
238    pub fn to_sat(&self) -> u64 {
239        self.0.to_sat()
240    }
241
242    /// Express this Amount as a floating-point value in Bitcoin. Please be aware of the risk of
243    /// using floating-point numbers.
244    pub fn to_btc(&self) -> f64 {
245        self.0.to_btc()
246    }
247}
248
249impl_from_core_type!(BdkAmount, Amount);
250impl_into_core_type!(Amount, BdkAmount);
251
252/// A bitcoin script: https://en.bitcoin.it/wiki/Script
253#[derive(Clone, Debug, uniffi::Object)]
254#[uniffi::export(Display)]
255pub struct Script(pub(crate) BdkScriptBuf);
256
257#[uniffi::export]
258impl Script {
259    /// Interpret an array of bytes as a bitcoin script.
260    #[uniffi::constructor]
261    pub fn new(raw_output_script: Vec<u8>) -> Self {
262        let script: BdkScriptBuf = raw_output_script.into();
263        Script(script)
264    }
265
266    /// Convert a script into an array of bytes.
267    pub fn to_bytes(&self) -> Vec<u8> {
268        self.0.to_bytes()
269    }
270}
271
272impl_from_core_type!(BdkScriptBuf, Script);
273impl_into_core_type!(Script, BdkScriptBuf);
274
275impl Display for Script {
276    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
277        self.0.fmt_asm(f)
278    }
279}
280
281/// Bitcoin block header.
282/// Contains all the block’s information except the actual transactions, but including a root of a merkle tree
283/// committing to all transactions in the block.
284#[derive(uniffi::Record)]
285pub struct Header {
286    /// Block version, now repurposed for soft fork signalling.
287    pub version: i32,
288    /// Reference to the previous block in the chain.
289    pub prev_blockhash: Arc<BlockHash>,
290    /// The root hash of the merkle tree of transactions in the block.
291    pub merkle_root: Arc<TxMerkleNode>,
292    /// The timestamp of the block, as claimed by the miner.
293    pub time: u32,
294    /// The target value below which the blockhash must lie.
295    pub bits: u32,
296    /// The nonce, selected to obtain a low enough blockhash.
297    pub nonce: u32,
298}
299
300impl From<BdkHeader> for Header {
301    fn from(bdk_header: BdkHeader) -> Self {
302        Header {
303            version: bdk_header.version.to_consensus(),
304            prev_blockhash: Arc::new(BlockHash(bdk_header.prev_blockhash)),
305            merkle_root: Arc::new(TxMerkleNode(bdk_header.merkle_root.to_raw_hash())),
306            time: bdk_header.time,
307            bits: bdk_header.bits.to_consensus(),
308            nonce: bdk_header.nonce,
309        }
310    }
311}
312
313/// Bitcoin block.
314/// A collection of transactions with an attached proof of work.
315#[derive(uniffi::Record)]
316pub struct Block {
317    pub header: Header,
318    pub txdata: Vec<Arc<Transaction>>,
319}
320
321impl From<BdkBlock> for Block {
322    fn from(bdk_block: BdkBlock) -> Self {
323        Block {
324            header: bdk_block.header.into(),
325            txdata: bdk_block
326                .txdata
327                .into_iter()
328                .map(|tx| Arc::new(tx.into()))
329                .collect(),
330        }
331    }
332}
333
334/// The type of address.
335#[derive(Debug, uniffi::Enum)]
336pub enum AddressData {
337    /// Legacy.
338    P2pkh { pubkey_hash: String },
339    /// Wrapped Segwit
340    P2sh { script_hash: String },
341    /// Segwit
342    Segwit { witness_program: WitnessProgram },
343}
344
345/// The version and program of a Segwit address.
346#[derive(Debug, uniffi::Record)]
347pub struct WitnessProgram {
348    /// Version. For example 1 for Taproot.
349    pub version: u8,
350    /// The witness program.
351    pub program: Vec<u8>,
352}
353
354/// A bitcoin address
355#[derive(Debug, PartialEq, Eq, uniffi::Object)]
356#[uniffi::export(Eq, Display)]
357pub struct Address(pub(crate) BdkAddress<NetworkChecked>);
358
359#[uniffi::export]
360impl Address {
361    /// Parse a string as an address for the given network.
362    #[uniffi::constructor]
363    pub fn new(address: String, network: Network) -> Result<Self, AddressParseError> {
364        let parsed_address = address.parse::<bdk_wallet::bitcoin::Address<NetworkUnchecked>>()?;
365        let network_checked_address = parsed_address.require_network(network)?;
366
367        Ok(Address(network_checked_address))
368    }
369
370    /// Parse a script as an address for the given network
371    #[uniffi::constructor]
372    pub fn from_script(script: Arc<Script>, network: Network) -> Result<Self, FromScriptError> {
373        let address = BdkAddress::from_script(&script.0.clone(), network)?;
374
375        Ok(Address(address))
376    }
377
378    /// Return the `scriptPubKey` underlying an address.
379    pub fn script_pubkey(&self) -> Arc<Script> {
380        Arc::new(Script(self.0.script_pubkey()))
381    }
382
383    /// Return a BIP-21 URI string for this address.
384    pub fn to_qr_uri(&self) -> String {
385        self.0.to_qr_uri()
386    }
387
388    /// Is the address valid for the provided network
389    pub fn is_valid_for_network(&self, network: Network) -> bool {
390        let address_str = self.0.to_string();
391        if let Ok(unchecked_address) = address_str.parse::<BdkAddress<NetworkUnchecked>>() {
392            unchecked_address.is_valid_for_network(network)
393        } else {
394            false
395        }
396    }
397
398    /// Return the data for the address.
399    pub fn to_address_data(&self) -> AddressData {
400        match self.0.to_address_data() {
401            BdkAddressData::P2pkh { pubkey_hash } => AddressData::P2pkh {
402                pubkey_hash: pubkey_hash.to_string(),
403            },
404            BdkAddressData::P2sh { script_hash } => AddressData::P2sh {
405                script_hash: script_hash.to_string(),
406            },
407            BdkAddressData::Segwit { witness_program } => AddressData::Segwit {
408                witness_program: WitnessProgram {
409                    version: witness_program.version().to_num(),
410                    program: witness_program.program().as_bytes().to_vec(),
411                },
412            },
413            // AddressData is marked #[non_exhaustive] in bitcoin crate
414            _ => unimplemented!("Unsupported address type"),
415        }
416    }
417}
418
419impl Display for Address {
420    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
421        write!(f, "{}", self.0)
422    }
423}
424
425impl_from_core_type!(BdkAddress, Address);
426impl_into_core_type!(Address, BdkAddress);
427
428/// Bitcoin transaction.
429/// An authenticated movement of coins.
430#[derive(Debug, Clone, PartialEq, Eq, uniffi::Object)]
431#[uniffi::export(Eq, Display)]
432pub struct Transaction(BdkTransaction);
433
434#[uniffi::export]
435impl Transaction {
436    /// Creates a new `Transaction` instance from serialized transaction bytes.
437    #[uniffi::constructor]
438    pub fn new(transaction_bytes: Vec<u8>) -> Result<Self, TransactionError> {
439        let mut decoder = Cursor::new(transaction_bytes);
440        let tx: BdkTransaction = BdkTransaction::consensus_decode(&mut decoder)?;
441        Ok(Transaction(tx))
442    }
443
444    /// Computes the Txid.
445    /// Hashes the transaction excluding the segwit data (i.e. the marker, flag bytes, and the witness fields themselves).
446    pub fn compute_txid(&self) -> Arc<Txid> {
447        Arc::new(Txid(self.0.compute_txid()))
448    }
449
450    /// Compute the Wtxid, which includes the witness in the transaction hash.
451    pub fn compute_wtxid(&self) -> Arc<Wtxid> {
452        Arc::new(Wtxid(self.0.compute_wtxid()))
453    }
454
455    /// Returns the weight of this transaction, as defined by BIP-141.
456    ///
457    /// > Transaction weight is defined as Base transaction size * 3 + Total transaction size (ie.
458    /// > the same method as calculating Block weight from Base size and Total size).
459    ///
460    /// For transactions with an empty witness, this is simply the consensus-serialized size times
461    /// four. For transactions with a witness, this is the non-witness consensus-serialized size
462    /// multiplied by three plus the with-witness consensus-serialized size.
463    ///
464    /// For transactions with no inputs, this function will return a value 2 less than the actual
465    /// weight of the serialized transaction. The reason is that zero-input transactions, post-segwit,
466    /// cannot be unambiguously serialized; we make a choice that adds two extra bytes. For more
467    /// details see [BIP 141](https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki)
468    /// which uses a "input count" of `0x00` as a `marker` for a Segwit-encoded transaction.
469    ///
470    /// If you need to use 0-input transactions, we strongly recommend you do so using the PSBT
471    /// API. The unsigned transaction encoded within PSBT is always a non-segwit transaction
472    /// and can therefore avoid this ambiguity.
473    #[inline]
474    pub fn weight(&self) -> u64 {
475        self.0.weight().to_wu()
476    }
477
478    /// Returns the total transaction size
479    ///
480    /// Total transaction size is the transaction size in bytes serialized as described in BIP144,
481    /// including base data and witness data.
482    pub fn total_size(&self) -> u64 {
483        self.0.total_size() as u64
484    }
485
486    /// Returns the "virtual size" (vsize) of this transaction.
487    ///
488    /// Will be `ceil(weight / 4.0)`. Note this implements the virtual size as per [`BIP141`], which
489    /// is different to what is implemented in Bitcoin Core.
490    /// > Virtual transaction size is defined as Transaction weight / 4 (rounded up to the next integer).
491    ///
492    /// [`BIP141`]: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki
493    #[inline]
494    pub fn vsize(&self) -> u64 {
495        self.0.vsize() as u64
496    }
497
498    /// Checks if this is a coinbase transaction.
499    /// The first transaction in the block distributes the mining reward and is called the coinbase transaction.
500    /// It is impossible to check if the transaction is first in the block, so this function checks the structure
501    /// of the transaction instead - the previous output must be all-zeros (creates satoshis “out of thin air”).
502    pub fn is_coinbase(&self) -> bool {
503        self.0.is_coinbase()
504    }
505
506    /// Returns `true` if the transaction itself opted in to be BIP-125-replaceable (RBF).
507    ///
508    /// # Warning
509    ///
510    /// **Incorrectly relying on RBF may lead to monetary loss!**
511    ///
512    /// This **does not** cover the case where a transaction becomes replaceable due to ancestors
513    /// being RBF. Please note that transactions **may be replaced** even if they **do not** include
514    /// the RBF signal: <https://bitcoinops.org/en/newsletters/2022/10/19/#transaction-replacement-option>.
515    pub fn is_explicitly_rbf(&self) -> bool {
516        self.0.is_explicitly_rbf()
517    }
518
519    /// Returns `true` if this transactions nLockTime is enabled ([BIP-65]).
520    ///
521    /// [BIP-65]: https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
522    pub fn is_lock_time_enabled(&self) -> bool {
523        self.0.is_lock_time_enabled()
524    }
525
526    /// The protocol version, is currently expected to be 1 or 2 (BIP 68).
527    pub fn version(&self) -> i32 {
528        self.0.version.0
529    }
530
531    /// Serialize transaction into consensus-valid format. See https://docs.rs/bitcoin/latest/bitcoin/struct.Transaction.html#serialization-notes for more notes on transaction serialization.
532    pub fn serialize(&self) -> Vec<u8> {
533        serialize(&self.0)
534    }
535
536    /// List of transaction inputs.
537    pub fn input(&self) -> Vec<TxIn> {
538        self.0.input.iter().map(|tx_in| tx_in.into()).collect()
539    }
540
541    /// List of transaction outputs.
542    pub fn output(&self) -> Vec<TxOut> {
543        self.0.output.iter().map(|tx_out| tx_out.into()).collect()
544    }
545
546    /// Block height or timestamp. Transaction cannot be included in a block until this height/time.
547    ///
548    /// /// ### Relevant BIPs
549    ///
550    /// * [BIP-65 OP_CHECKLOCKTIMEVERIFY](https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki)
551    /// * [BIP-113 Median time-past as endpoint for lock-time calculations](https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki)
552    pub fn lock_time(&self) -> u32 {
553        self.0.lock_time.to_consensus_u32()
554    }
555}
556
557impl From<BdkTransaction> for Transaction {
558    fn from(tx: BdkTransaction) -> Self {
559        Transaction(tx)
560    }
561}
562
563impl From<&BdkTransaction> for Transaction {
564    fn from(tx: &BdkTransaction) -> Self {
565        Transaction(tx.clone())
566    }
567}
568
569impl From<&Transaction> for BdkTransaction {
570    fn from(tx: &Transaction) -> Self {
571        tx.0.clone()
572    }
573}
574
575impl Display for Transaction {
576    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
577        write!(f, "{:?}", self.0)
578    }
579}
580
581#[derive(Clone, Debug, uniffi::Record)]
582pub struct TapScriptEntry {
583    /// script (reuse existing `Script` FFI type)
584    pub script: Arc<Script>,
585    /// leaf version
586    pub leaf_version: u8,
587}
588
589#[derive(Clone, Debug, uniffi::Record)]
590pub struct TapKeyOrigin {
591    /// leaf hashes as hex strings
592    pub tap_leaf_hashes: Vec<String>,
593    /// key source
594    pub key_source: KeySource,
595}
596
597#[derive(Clone, Debug, uniffi::Record)]
598pub struct KeySource {
599    /// A fingerprint
600    pub fingerprint: String,
601    /// A BIP-32 derivation path.
602    pub path: Arc<DerivationPath>,
603}
604
605#[derive(Clone, Debug, Hash, Eq, PartialEq, uniffi::Record)]
606pub struct Key {
607    /// The type of this PSBT key.
608    pub type_value: u8,
609    /// The key itself in raw byte form.
610    /// `<key> := <keylen> <keytype> <keydata>`
611    pub key: Vec<u8>,
612}
613
614#[derive(Clone, Debug, Hash, Eq, PartialEq, uniffi::Record)]
615pub struct ProprietaryKey {
616    /// Proprietary type prefix used for grouping together keys under some
617    /// application and avoid namespace collision
618    pub prefix: Vec<u8>,
619    /// Custom proprietary subtype
620    pub subtype: u8,
621    /// Additional key bytes (like serialized public key data etc)
622    pub key: Vec<u8>,
623}
624
625#[derive(Clone, Debug, Hash, Eq, PartialEq, uniffi::Record)]
626pub struct ControlBlock {
627    /// The internal key.
628    pub internal_key: Vec<u8>,
629    /// The merkle proof of a script associated with this leaf.
630    pub merkle_branch: Vec<String>,
631    /// The parity of the output key (NOT THE INTERNAL KEY WHICH IS ALWAYS XONLY).
632    pub output_key_parity: u8,
633    /// The tapleaf version.
634    pub leaf_version: u8,
635}
636
637#[derive(Clone, Debug, Hash, Eq, PartialEq, uniffi::Record)]
638pub struct TapScriptSigKey {
639    /// An x-only public key, used for verification of Taproot signatures and serialized according to BIP-340.
640    pub xonly_pubkey: String,
641    /// Taproot-tagged hash with tag "TapLeaf".
642    /// This is used for computing tapscript script spend hash.
643    pub tap_leaf_hash: String,
644}
645
646/// A key-value map for an input of the corresponding index in the unsigned transaction.
647#[derive(Clone, Debug, uniffi::Record)]
648pub struct Input {
649    /// The non-witness transaction this input spends from. Should only be
650    /// `Option::Some` for inputs which spend non-segwit outputs or
651    /// if it is unknown whether an input spends a segwit output.
652    pub non_witness_utxo: Option<Arc<Transaction>>,
653    /// The transaction output this input spends from. Should only be
654    /// `Option::Some` for inputs which spend segwit outputs,
655    /// including P2SH embedded ones.
656    pub witness_utxo: Option<TxOut>,
657    /// A map from public keys to their corresponding signature as would be
658    /// pushed to the stack from a scriptSig or witness for a non-taproot inputs.
659    pub partial_sigs: HashMap<String, Vec<u8>>,
660    /// The sighash type to be used for this input. Signatures for this input
661    /// must use the sighash type.
662    pub sighash_type: Option<String>,
663    /// The redeem script for this input.
664    pub redeem_script: Option<Arc<Script>>,
665    /// The witness script for this input.
666    pub witness_script: Option<Arc<Script>>,
667    /// A map from public keys needed to sign this input to their corresponding
668    /// master key fingerprints and derivation paths.
669    pub bip32_derivation: HashMap<String, KeySource>,
670
671    /// The finalized, fully-constructed scriptSig with signatures and any other
672    /// scripts necessary for this input to pass validation.
673    pub final_script_sig: Option<Arc<Script>>,
674
675    /// The finalized, fully-constructed scriptWitness with signatures and any
676    /// other scripts necessary for this input to pass validation.
677    pub final_script_witness: Option<Vec<Vec<u8>>>,
678    /// RIPEMD160 hash to preimage map.
679    pub ripemd160_preimages: HashMap<String, Vec<u8>>,
680    /// SHA256 hash to preimage map.
681    pub sha256_preimages: HashMap<String, Vec<u8>>,
682    /// HASH160 hash to preimage map.
683    pub hash160_preimages: HashMap<String, Vec<u8>>,
684    /// HASH256 hash to preimage map.
685    pub hash256_preimages: HashMap<String, Vec<u8>>,
686    /// Serialized taproot signature with sighash type for key spend.
687    pub tap_key_sig: Option<Vec<u8>>,
688    /// Map of `<xonlypubkey>|<leafhash>` with signature.
689    pub tap_script_sigs: HashMap<TapScriptSigKey, Vec<u8>>,
690    /// Map of Control blocks to Script version pair.
691    pub tap_scripts: HashMap<ControlBlock, TapScriptEntry>,
692    /// Map of tap root x only keys to origin info and leaf hashes contained in it.
693    pub tap_key_origins: HashMap<String, TapKeyOrigin>,
694    /// Taproot Internal key.
695    pub tap_internal_key: Option<String>,
696    /// Taproot Merkle root.
697    pub tap_merkle_root: Option<String>,
698    /// Proprietary key-value pairs for this input.
699    pub proprietary: HashMap<ProprietaryKey, Vec<u8>>,
700    /// Unknown key-value pairs for this input.
701    pub unknown: HashMap<Key, Vec<u8>>,
702}
703
704use crate::error::AddForeignUtxoError;
705
706impl From<&BdkInput> for Input {
707    fn from(input: &BdkInput) -> Self {
708        Input {
709            non_witness_utxo: input
710                .non_witness_utxo
711                .as_ref()
712                .map(|tx| Arc::new(Transaction(tx.clone()))),
713            witness_utxo: input.witness_utxo.as_ref().map(TxOut::from),
714            partial_sigs: input
715                .partial_sigs
716                .iter()
717                .map(|(k, v)| (k.to_string(), v.to_vec()))
718                .collect(),
719            sighash_type: input.sighash_type.as_ref().map(|s| s.to_string()),
720            redeem_script: input
721                .redeem_script
722                .as_ref()
723                .map(|s| Arc::new(Script(s.clone()))),
724            witness_script: input
725                .witness_script
726                .as_ref()
727                .map(|s| Arc::new(Script(s.clone()))),
728            bip32_derivation: input
729                .bip32_derivation
730                .iter()
731                .map(|(pk, (fingerprint, deriv_path))| {
732                    (
733                        pk.to_string(),
734                        KeySource {
735                            fingerprint: fingerprint.to_string(),
736                            path: Arc::new(deriv_path.clone().into()),
737                        },
738                    )
739                })
740                .collect(),
741            final_script_sig: input
742                .final_script_sig
743                .as_ref()
744                .map(|s| Arc::new(Script(s.clone()))),
745            final_script_witness: input.final_script_witness.as_ref().map(|w| w.to_vec()),
746            ripemd160_preimages: input
747                .ripemd160_preimages
748                .iter()
749                .map(|(k, v)| (k.to_string(), v.clone()))
750                .collect(),
751            sha256_preimages: input
752                .sha256_preimages
753                .iter()
754                .map(|(k, v)| (k.to_string(), v.clone()))
755                .collect(),
756            hash160_preimages: input
757                .hash160_preimages
758                .iter()
759                .map(|(k, v)| (k.to_string(), v.clone()))
760                .collect(),
761            hash256_preimages: input
762                .hash256_preimages
763                .iter()
764                .map(|(k, v)| (k.to_string(), v.clone()))
765                .collect(),
766            tap_key_sig: input.tap_key_sig.as_ref().map(|s| s.serialize().to_vec()),
767            tap_script_sigs: input
768                .tap_script_sigs
769                .iter()
770                .map(|(k, v)| {
771                    let key = TapScriptSigKey {
772                        xonly_pubkey: k.0.to_string(),
773                        tap_leaf_hash: k.1.to_string(),
774                    };
775                    (key, v.to_vec())
776                })
777                .collect(),
778            tap_scripts: input
779                .tap_scripts
780                .iter()
781                .map(|(k, v)| {
782                    let key = ControlBlock {
783                        internal_key: k.internal_key.serialize().to_vec(),
784                        merkle_branch: k.merkle_branch.iter().map(|h| h.to_string()).collect(),
785                        output_key_parity: k.output_key_parity.to_u8(),
786                        leaf_version: k.leaf_version.to_consensus(),
787                    };
788                    let entry = TapScriptEntry {
789                        script: Arc::new(v.0.clone().into()),
790                        leaf_version: v.1.to_consensus(),
791                    };
792                    (key, entry)
793                })
794                .collect(),
795            tap_key_origins: input
796                .tap_key_origins
797                .iter()
798                .map(|(k, v)| {
799                    let key = k.to_string();
800                    let value = TapKeyOrigin {
801                        tap_leaf_hashes: v.0.iter().map(|h| h.to_string()).collect(),
802                        key_source: KeySource {
803                            // Unnecessary spaces being added by fmt. We use #[rustfmt::skip] to avoid them for now.
804                            #[rustfmt::skip]
805                            fingerprint: v.1.0.to_string(),
806                            #[rustfmt::skip]
807                            path: Arc::new(v.1.1.clone().into()),
808                        },
809                    };
810                    (key, value)
811                })
812                .collect(),
813            tap_internal_key: input.tap_internal_key.as_ref().map(|k| k.to_string()),
814            tap_merkle_root: input.tap_merkle_root.as_ref().map(|k| k.to_string()),
815            proprietary: input
816                .proprietary
817                .iter()
818                .map(|(k, v)| {
819                    (
820                        ProprietaryKey {
821                            prefix: k.prefix.clone(),
822                            subtype: k.subtype,
823                            key: k.key.clone(),
824                        },
825                        v.to_vec(),
826                    )
827                })
828                .collect(),
829            unknown: input
830                .unknown
831                .iter()
832                .map(|(k, v)| {
833                    (
834                        Key {
835                            key: k.key.clone(),
836                            type_value: k.type_value,
837                        },
838                        v.to_vec(),
839                    )
840                })
841                .collect(),
842        }
843    }
844}
845
846impl TryFrom<Input> for BdkInput {
847    type Error = AddForeignUtxoError;
848
849    fn try_from(input: Input) -> Result<Self, Self::Error> {
850        use bdk_wallet::bitcoin::ecdsa;
851        use bdk_wallet::bitcoin::hashes::Hash as HashTrait;
852        use bdk_wallet::bitcoin::key::PublicKey as Secp256k1PublicKey;
853        use bdk_wallet::bitcoin::psbt::PsbtSighashType;
854        use bdk_wallet::bitcoin::secp256k1::XOnlyPublicKey;
855        use bdk_wallet::bitcoin::taproot::{
856            ControlBlock as BdkControlBlock, LeafVersion, TapLeafHash, TapNodeHash,
857        };
858        use std::str::FromStr;
859
860        let non_witness_utxo = input.non_witness_utxo.map(|tx| tx.0.clone());
861
862        let witness_utxo = input.witness_utxo.map(|txout| txout.into());
863
864        let partial_sigs = input
865            .partial_sigs
866            .into_iter()
867            .map(|(k, v)| {
868                let pubkey = Secp256k1PublicKey::from_str(&k).map_err(|e| {
869                    AddForeignUtxoError::InputConversionError {
870                        error_message: format!("invalid public key in partial_sigs: {}", e),
871                    }
872                })?;
873                let sig = ecdsa::Signature::from_slice(&v).map_err(|e| {
874                    AddForeignUtxoError::InputConversionError {
875                        error_message: format!("invalid signature in partial_sigs: {}", e),
876                    }
877                })?;
878                Ok((pubkey, sig))
879            })
880            .collect::<Result<std::collections::BTreeMap<_, _>, AddForeignUtxoError>>()?;
881
882        let sighash_type = input
883            .sighash_type
884            .map(|s| {
885                PsbtSighashType::from_str(&s).map_err(|e| {
886                    AddForeignUtxoError::InputConversionError {
887                        error_message: format!("invalid sighash type: {}", e),
888                    }
889                })
890            })
891            .transpose()?;
892
893        let redeem_script = input.redeem_script.map(|s| s.0.clone());
894        let witness_script = input.witness_script.map(|s| s.0.clone());
895
896        let bip32_derivation = input
897            .bip32_derivation
898            .into_iter()
899            .map(|(k, v)| {
900                use bdk_wallet::bitcoin::bip32::{DerivationPath, Fingerprint};
901                use bdk_wallet::bitcoin::secp256k1::PublicKey as Secp256k1RawPublicKey;
902                let pubkey = Secp256k1RawPublicKey::from_str(&k).map_err(|e| {
903                    AddForeignUtxoError::InputConversionError {
904                        error_message: format!("invalid public key in bip32_derivation: {}", e),
905                    }
906                })?;
907                let fingerprint = Fingerprint::from_str(&v.fingerprint).map_err(|e| {
908                    AddForeignUtxoError::InputConversionError {
909                        error_message: format!("invalid fingerprint: {}", e),
910                    }
911                })?;
912                let path: DerivationPath = v.path.0.clone();
913                Ok((pubkey, (fingerprint, path)))
914            })
915            .collect::<Result<std::collections::BTreeMap<_, _>, AddForeignUtxoError>>()?;
916
917        let final_script_sig = input.final_script_sig.map(|s| s.0.clone());
918
919        let final_script_witness = input.final_script_witness.map(|w| {
920            use bdk_wallet::bitcoin::Witness;
921            Witness::from_slice(&w)
922        });
923
924        let ripemd160_preimages = input
925            .ripemd160_preimages
926            .into_iter()
927            .map(|(k, v)| {
928                use bdk_wallet::bitcoin::hashes::ripemd160;
929                let hash = ripemd160::Hash::from_str(&k).map_err(|e| {
930                    AddForeignUtxoError::InputConversionError {
931                        error_message: format!("invalid ripemd160 hash: {}", e),
932                    }
933                })?;
934                Ok((hash, v))
935            })
936            .collect::<Result<_, AddForeignUtxoError>>()?;
937
938        let sha256_preimages = input
939            .sha256_preimages
940            .into_iter()
941            .map(|(k, v)| {
942                use bdk_wallet::bitcoin::hashes::sha256;
943                let hash = sha256::Hash::from_str(&k).map_err(|e| {
944                    AddForeignUtxoError::InputConversionError {
945                        error_message: format!("invalid sha256 hash: {}", e),
946                    }
947                })?;
948                Ok((hash, v))
949            })
950            .collect::<Result<_, AddForeignUtxoError>>()?;
951
952        let hash160_preimages = input
953            .hash160_preimages
954            .into_iter()
955            .map(|(k, v)| {
956                use bdk_wallet::bitcoin::hashes::hash160;
957                let hash = hash160::Hash::from_str(&k).map_err(|e| {
958                    AddForeignUtxoError::InputConversionError {
959                        error_message: format!("invalid hash160: {}", e),
960                    }
961                })?;
962                Ok((hash, v))
963            })
964            .collect::<Result<_, AddForeignUtxoError>>()?;
965
966        let hash256_preimages = input
967            .hash256_preimages
968            .into_iter()
969            .map(|(k, v)| {
970                use bdk_wallet::bitcoin::hashes::sha256d;
971                let hash = sha256d::Hash::from_str(&k).map_err(|e| {
972                    AddForeignUtxoError::InputConversionError {
973                        error_message: format!("invalid hash256: {}", e),
974                    }
975                })?;
976                Ok((hash, v))
977            })
978            .collect::<Result<_, AddForeignUtxoError>>()?;
979
980        let tap_key_sig = input
981            .tap_key_sig
982            .map(|s| {
983                use bdk_wallet::bitcoin::taproot::Signature;
984                Signature::from_slice(&s).map_err(|e| AddForeignUtxoError::InputConversionError {
985                    error_message: format!("invalid taproot signature: {}", e),
986                })
987            })
988            .transpose()?;
989
990        let tap_script_sigs = input
991            .tap_script_sigs
992            .into_iter()
993            .map(|(k, v)| {
994                use bdk_wallet::bitcoin::taproot::Signature;
995                let xonly = XOnlyPublicKey::from_str(&k.xonly_pubkey).map_err(|e| {
996                    AddForeignUtxoError::InputConversionError {
997                        error_message: format!("invalid xonly pubkey: {}", e),
998                    }
999                })?;
1000                let leaf_hash = TapLeafHash::from_str(&k.tap_leaf_hash).map_err(|e| {
1001                    AddForeignUtxoError::InputConversionError {
1002                        error_message: format!("invalid tap leaf hash: {}", e),
1003                    }
1004                })?;
1005                let sig = Signature::from_slice(&v).map_err(|e| {
1006                    AddForeignUtxoError::InputConversionError {
1007                        error_message: format!("invalid taproot script signature: {}", e),
1008                    }
1009                })?;
1010                Ok(((xonly, leaf_hash), sig))
1011            })
1012            .collect::<Result<_, AddForeignUtxoError>>()?;
1013
1014        let tap_scripts = input
1015            .tap_scripts
1016            .into_iter()
1017            .map(|(k, v)| {
1018                use bdk_wallet::bitcoin::key::XOnlyPublicKey as BdkXOnlyPublicKey;
1019                use bdk_wallet::bitcoin::taproot::TapNodeHash;
1020
1021                let internal_key = BdkXOnlyPublicKey::from_slice(&k.internal_key).map_err(|e| {
1022                    AddForeignUtxoError::InputConversionError {
1023                        error_message: format!("invalid internal key: {}", e),
1024                    }
1025                })?;
1026
1027                let output_key_parity = k.output_key_parity;
1028                let leaf_version_u8 = k.leaf_version;
1029
1030                let merkle_branch: Vec<TapNodeHash> = k
1031                    .merkle_branch
1032                    .into_iter()
1033                    .map(|h| {
1034                        TapNodeHash::from_str(&h).map_err(|e| {
1035                            AddForeignUtxoError::InputConversionError {
1036                                error_message: format!("invalid merkle branch hash: {}", e),
1037                            }
1038                        })
1039                    })
1040                    .collect::<Result<_, AddForeignUtxoError>>()?;
1041
1042                let mut control_block_bytes = vec![output_key_parity | leaf_version_u8];
1043                control_block_bytes.extend_from_slice(&internal_key.serialize());
1044                for hash in &merkle_branch {
1045                    control_block_bytes.extend_from_slice(&hash.to_byte_array());
1046                }
1047
1048                let control_block = BdkControlBlock::decode(&control_block_bytes).map_err(|e| {
1049                    AddForeignUtxoError::InputConversionError {
1050                        error_message: format!("invalid control block: {}", e),
1051                    }
1052                })?;
1053
1054                let leaf_version = LeafVersion::from_consensus(leaf_version_u8).map_err(|_| {
1055                    AddForeignUtxoError::InputConversionError {
1056                        error_message: format!("invalid leaf version: {}", leaf_version_u8),
1057                    }
1058                })?;
1059
1060                Ok((control_block, (v.script.0.clone(), leaf_version)))
1061            })
1062            .collect::<Result<_, AddForeignUtxoError>>()?;
1063
1064        let tap_key_origins = input
1065            .tap_key_origins
1066            .into_iter()
1067            .map(|(k, v)| {
1068                use bdk_wallet::bitcoin::bip32::{DerivationPath, Fingerprint};
1069
1070                let xonly = XOnlyPublicKey::from_str(&k).map_err(|e| {
1071                    AddForeignUtxoError::InputConversionError {
1072                        error_message: format!("invalid xonly pubkey in tap_key_origins: {}", e),
1073                    }
1074                })?;
1075
1076                let leaf_hashes: Vec<TapLeafHash> = v
1077                    .tap_leaf_hashes
1078                    .into_iter()
1079                    .map(|h| {
1080                        TapLeafHash::from_str(&h).map_err(|e| {
1081                            AddForeignUtxoError::InputConversionError {
1082                                error_message: format!("invalid tap leaf hash: {}", e),
1083                            }
1084                        })
1085                    })
1086                    .collect::<Result<_, AddForeignUtxoError>>()?;
1087
1088                let fingerprint =
1089                    Fingerprint::from_str(&v.key_source.fingerprint).map_err(|e| {
1090                        AddForeignUtxoError::InputConversionError {
1091                            error_message: format!("invalid fingerprint in tap_key_origins: {}", e),
1092                        }
1093                    })?;
1094
1095                let path: DerivationPath = v.key_source.path.0.clone();
1096
1097                Ok((xonly, (leaf_hashes, (fingerprint, path))))
1098            })
1099            .collect::<Result<_, AddForeignUtxoError>>()?;
1100
1101        let tap_internal_key = input
1102            .tap_internal_key
1103            .map(|k| {
1104                XOnlyPublicKey::from_str(&k).map_err(|e| {
1105                    AddForeignUtxoError::InputConversionError {
1106                        error_message: format!("invalid tap internal key: {}", e),
1107                    }
1108                })
1109            })
1110            .transpose()?;
1111
1112        let tap_merkle_root = input
1113            .tap_merkle_root
1114            .map(|k| {
1115                TapNodeHash::from_str(&k).map_err(|e| AddForeignUtxoError::InputConversionError {
1116                    error_message: format!("invalid tap merkle root: {}", e),
1117                })
1118            })
1119            .transpose()?;
1120
1121        let proprietary = input
1122            .proprietary
1123            .into_iter()
1124            .map(|(k, v)| {
1125                use bdk_wallet::bitcoin::psbt::raw::ProprietaryKey as BdkProprietaryKey;
1126                (
1127                    BdkProprietaryKey {
1128                        prefix: k.prefix,
1129                        subtype: k.subtype,
1130                        key: k.key,
1131                    },
1132                    v,
1133                )
1134            })
1135            .collect();
1136
1137        let unknown = input
1138            .unknown
1139            .into_iter()
1140            .map(|(k, v)| {
1141                use bdk_wallet::bitcoin::psbt::raw::Key as BdkKey;
1142                (
1143                    BdkKey {
1144                        type_value: k.type_value,
1145                        key: k.key,
1146                    },
1147                    v,
1148                )
1149            })
1150            .collect();
1151
1152        Ok(BdkInput {
1153            non_witness_utxo,
1154            witness_utxo,
1155            partial_sigs,
1156            sighash_type,
1157            redeem_script,
1158            witness_script,
1159            bip32_derivation,
1160            final_script_sig,
1161            final_script_witness,
1162            ripemd160_preimages,
1163            sha256_preimages,
1164            hash160_preimages,
1165            hash256_preimages,
1166            tap_key_sig,
1167            tap_script_sigs,
1168            tap_scripts,
1169            tap_key_origins,
1170            tap_internal_key,
1171            tap_merkle_root,
1172            proprietary,
1173            unknown,
1174        })
1175    }
1176}
1177
1178/// Store information about taproot leaf node.
1179#[derive(Debug, uniffi::Object)]
1180#[uniffi::export(Display)]
1181pub struct LeafNode(BdkLeafNode);
1182
1183#[uniffi::export]
1184impl LeafNode {
1185    /// Returns the depth of this script leaf in the tap tree.
1186    pub fn depth(&self) -> u8 {
1187        self.0.depth()
1188    }
1189
1190    /// Computes a leaf hash for this ScriptLeaf if the leaf is known.
1191    /// This TapLeafHash is useful while signing taproot script spends.
1192    /// See LeafNode::node_hash for computing the TapNodeHash which returns the hidden node hash if the node is hidden.
1193    pub fn leaf_hash(&self) -> Option<String> {
1194        self.0.leaf_hash().map(|h| h.to_string())
1195    }
1196
1197    /// Computes the [`TapNodeHash`] for this [`ScriptLeaf`]. This returns the
1198    /// leaf hash if the leaf is known and the hidden node hash if the leaf is
1199    /// hidden.
1200    /// See also, [`bdk_electrum::bdk_core::bitcoin::taproot::LeafNode::leaf_hash`].
1201    pub fn node_hash(&self) -> String {
1202        self.0.node_hash().to_string()
1203    }
1204
1205    /// Returns reference to the leaf script if the leaf is known.
1206    pub fn script(&self) -> Option<Arc<Script>> {
1207        self.0.script().map(|s| Arc::new(Script(s.to_owned())))
1208    }
1209
1210    /// Returns leaf version of the script if the leaf is known.
1211    pub fn leaf_version(&self) -> Option<u8> {
1212        self.0.leaf_version().map(|n| n.to_consensus())
1213    }
1214
1215    /// Returns reference to the merkle proof (hashing partners) to get this
1216    /// node in form of [`TaprootMerkleBranch`].
1217    pub fn merkle_branch(&self) -> Vec<String> {
1218        self.0
1219            .merkle_branch()
1220            .to_vec()
1221            .iter()
1222            .map(|h| h.to_string())
1223            .collect()
1224    }
1225}
1226
1227impl Display for LeafNode {
1228    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1229        write!(f, "{:?}", self)
1230    }
1231}
1232
1233/// Taproot Tree representing a complete binary tree without any hidden nodes.
1234///
1235/// This is in contrast to NodeInfo, which allows hidden nodes. The implementations for Eq, PartialEq and Hash compare the merkle root of the tree
1236#[derive(Debug, uniffi::Object)]
1237#[uniffi::export(Display)]
1238pub struct TapTree(BdkTapTree);
1239
1240#[uniffi::export]
1241impl TapTree {
1242    /// Returns the root TapNodeHash of this tree.
1243    pub fn root_hash(&self) -> String {
1244        self.0.root_hash().to_string()
1245    }
1246
1247    /// Gets the reference to inner NodeInfo of this tree root.
1248    pub fn node_info(&self) -> Arc<NodeInfo> {
1249        Arc::new(NodeInfo(self.0.node_info().clone()))
1250    }
1251}
1252
1253impl Display for TapTree {
1254    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1255        write!(f, "{:?}", self)
1256    }
1257}
1258
1259/// Represents the node information in taproot tree. In contrast to TapTree, this is allowed to have hidden leaves as children.
1260///
1261/// Helper type used in merkle tree construction allowing one to build sparse merkle trees. The node represents part of the tree that has information about all of its descendants. See how TaprootBuilder works for more details.
1262/// You can use TaprootSpendInfo::from_node_info to a get a TaprootSpendInfo from the merkle root NodeInfo.
1263#[derive(Debug, uniffi::Object)]
1264#[uniffi::export(Display)]
1265pub struct NodeInfo(BdkNodeInfo);
1266
1267#[uniffi::export]
1268impl NodeInfo {
1269    /// Creates an iterator over all leaves (including hidden leaves) in the tree.
1270    pub fn leaf_nodes(&self) -> Vec<Arc<LeafNode>> {
1271        self.0
1272            .leaf_nodes()
1273            .map(|ln| Arc::new(LeafNode(ln.clone())))
1274            .collect()
1275    }
1276
1277    /// Returns the root TapNodeHash of this node info.
1278    pub fn node_hash(&self) -> String {
1279        self.0.node_hash().to_string()
1280    }
1281}
1282
1283impl Display for NodeInfo {
1284    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1285        write!(f, "{:?}", self)
1286    }
1287}
1288
1289/// A key-value map for an output of the corresponding index in the unsigned
1290/// transaction.
1291#[derive(Debug, uniffi::Record)]
1292pub struct Output {
1293    /// The redeem script for this output.
1294    pub redeem_script: Option<Arc<Script>>,
1295    /// The witness script for this output.
1296    pub witness_script: Option<Arc<Script>>,
1297    /// Map of public keys needed to spend this output to their corresponding
1298    /// master key fingerprints and derivation paths.
1299    pub bip32_derivation: HashMap<String, KeySource>,
1300    /// Taproot Internal key.
1301    pub tap_internal_key: Option<String>,
1302    /// Taproot Output tree (structured record).
1303    pub tap_tree: Option<Arc<TapTree>>,
1304    /// Map of tap root x only keys to origin info and leaf hashes contained in it.
1305    pub tap_key_origins: HashMap<String, TapKeyOrigin>,
1306    /// Proprietary key-value pairs for this output.
1307    pub proprietary: HashMap<ProprietaryKey, Vec<u8>>,
1308    /// Unknown key-value pairs for this output.
1309    pub unknown: HashMap<Key, Vec<u8>>,
1310}
1311
1312impl From<&BdkOutput> for Output {
1313    fn from(output: &BdkOutput) -> Self {
1314        Output {
1315            redeem_script: output
1316                .redeem_script
1317                .as_ref()
1318                .map(|s| Arc::new(Script(s.clone()))),
1319            witness_script: output
1320                .witness_script
1321                .as_ref()
1322                .map(|s| Arc::new(Script(s.clone()))),
1323            bip32_derivation: output
1324                .bip32_derivation
1325                .iter()
1326                .map(|(pk, (fingerprint, deriv_path))| {
1327                    (
1328                        pk.to_string(),
1329                        KeySource {
1330                            fingerprint: fingerprint.to_string(),
1331                            path: Arc::new(deriv_path.clone().into()),
1332                        },
1333                    )
1334                })
1335                .collect(),
1336            tap_internal_key: output.tap_internal_key.as_ref().map(|k| k.to_string()),
1337            tap_tree: output
1338                .tap_tree
1339                .as_ref()
1340                .map(|t| Arc::new(TapTree(t.clone()))),
1341            tap_key_origins: output
1342                .tap_key_origins
1343                .iter()
1344                .map(|(k, v)| {
1345                    let key = k.to_string();
1346                    let value = TapKeyOrigin {
1347                        tap_leaf_hashes: v.0.iter().map(|h| h.to_string()).collect(),
1348                        key_source: KeySource {
1349                            // Unnecessary spaces being added by fmt. We use #[rustfmt::skip] to avoid them for now.
1350                            #[rustfmt::skip]
1351                            fingerprint: v.1.0.to_string(),
1352                            #[rustfmt::skip]
1353                            path: Arc::new(v.1.1.clone().into()),
1354                        },
1355                    };
1356                    (key, value)
1357                })
1358                .collect(),
1359            proprietary: output
1360                .proprietary
1361                .iter()
1362                .map(|(k, v)| {
1363                    (
1364                        ProprietaryKey {
1365                            prefix: k.prefix.clone(),
1366                            subtype: k.subtype,
1367                            key: k.key.clone(),
1368                        },
1369                        v.to_vec(),
1370                    )
1371                })
1372                .collect(),
1373            unknown: output
1374                .unknown
1375                .iter()
1376                .map(|(k, v)| {
1377                    (
1378                        Key {
1379                            key: k.key.clone(),
1380                            type_value: k.type_value,
1381                        },
1382                        v.to_vec(),
1383                    )
1384                })
1385                .collect(),
1386        }
1387    }
1388}
1389
1390/// A Partially Signed Transaction.
1391#[derive(uniffi::Object)]
1392pub struct Psbt(pub(crate) Mutex<BdkPsbt>);
1393
1394#[uniffi::export]
1395impl Psbt {
1396    /// Creates a new `Psbt` instance from a base64-encoded string.
1397    #[uniffi::constructor]
1398    pub fn new(psbt_base64: String) -> Result<Self, PsbtParseError> {
1399        let psbt: BdkPsbt = BdkPsbt::from_str(&psbt_base64)?;
1400        Ok(Psbt(Mutex::new(psbt)))
1401    }
1402
1403    /// Creates a PSBT from an unsigned transaction.
1404    ///
1405    /// # Errors
1406    ///
1407    /// If transactions is not unsigned.
1408    #[uniffi::constructor]
1409    pub fn from_unsigned_tx(tx: Arc<Transaction>) -> Result<Arc<Psbt>, PsbtError> {
1410        let psbt: BdkPsbt = BdkPsbt::from_unsigned_tx(tx.0.clone())?;
1411        Ok(Arc::new(Psbt(Mutex::new(psbt))))
1412    }
1413
1414    /// Create a new `Psbt` from a `.psbt` file.
1415    #[uniffi::constructor]
1416    pub fn from_file(path: String) -> Result<Self, PsbtError> {
1417        let file = File::open(path)?;
1418        let mut buf_read = BufReader::new(file);
1419        let psbt: BdkPsbt = BdkPsbt::deserialize_from_reader(&mut buf_read)?;
1420        Ok(Psbt(Mutex::new(psbt)))
1421    }
1422
1423    /// Serialize the PSBT into a base64-encoded string.
1424    pub fn serialize(&self) -> String {
1425        let psbt = self.0.lock().unwrap().clone();
1426        psbt.to_string()
1427    }
1428
1429    /// Extracts the `Transaction` from a `Psbt` by filling in the available signature information.
1430    ///
1431    /// #### Errors
1432    ///
1433    /// `ExtractTxError` variants will contain either the `Psbt` itself or the `Transaction`
1434    /// that was extracted. These can be extracted from the Errors in order to recover.
1435    /// See the error documentation for info on the variants. In general, it covers large fees.
1436    pub fn extract_tx(&self) -> Result<Arc<Transaction>, ExtractTxError> {
1437        let tx: BdkTransaction = self.0.lock().unwrap().clone().extract_tx()?;
1438        let transaction: Transaction = tx.into();
1439        Ok(Arc::new(transaction))
1440    }
1441
1442    /// Calculates transaction fee.
1443    ///
1444    /// 'Fee' being the amount that will be paid for mining a transaction with the current inputs
1445    /// and outputs i.e., the difference in value of the total inputs and the total outputs.
1446    ///
1447    /// #### Errors
1448    ///
1449    /// - `MissingUtxo` when UTXO information for any input is not present or is invalid.
1450    /// - `NegativeFee` if calculated value is negative.
1451    /// - `FeeOverflow` if an integer overflow occurs.
1452    pub fn fee(&self) -> Result<u64, PsbtError> {
1453        self.0
1454            .lock()
1455            .unwrap()
1456            .fee()
1457            .map(|fee| fee.to_sat())
1458            .map_err(PsbtError::from)
1459    }
1460
1461    /// Combines this `Psbt` with `other` PSBT as described by BIP 174.
1462    ///
1463    /// In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)`
1464    pub fn combine(&self, other: Arc<Psbt>) -> Result<Arc<Psbt>, PsbtError> {
1465        let mut original_psbt = self.0.lock().unwrap().clone();
1466        let other_psbt = other.0.lock().unwrap().clone();
1467        original_psbt.combine(other_psbt)?;
1468        Ok(Arc::new(Psbt(Mutex::new(original_psbt))))
1469    }
1470
1471    /// Finalizes the current PSBT and produces a result indicating
1472    ///
1473    /// whether the finalization was successful or not.
1474    pub fn finalize(&self) -> FinalizedPsbtResult {
1475        let curve = Secp256k1::verification_only();
1476        let finalized = self.0.lock().unwrap().clone().finalize(&curve);
1477        match finalized {
1478            Ok(psbt) => FinalizedPsbtResult {
1479                psbt: Arc::new(psbt.into()),
1480                could_finalize: true,
1481                errors: None,
1482            },
1483            Err((psbt, errors)) => {
1484                let errors = errors.into_iter().map(|e| e.into()).collect();
1485                FinalizedPsbtResult {
1486                    psbt: Arc::new(psbt.into()),
1487                    could_finalize: false,
1488                    errors: Some(errors),
1489                }
1490            }
1491        }
1492    }
1493
1494    /// Write the `Psbt` to a file. Note that the file must not yet exist.
1495    pub fn write_to_file(&self, path: String) -> Result<(), PsbtError> {
1496        let file = File::create_new(path)?;
1497        let mut writer = BufWriter::new(file);
1498        let psbt = self.0.lock().unwrap();
1499        psbt.serialize_to_writer(&mut writer)?;
1500        Ok(())
1501    }
1502
1503    /// Serializes the PSBT into a JSON string representation.
1504    pub fn json_serialize(&self) -> String {
1505        let psbt = self.0.lock().unwrap();
1506        serde_json::to_string(psbt.deref()).unwrap()
1507    }
1508
1509    /// Returns the spending utxo for this PSBT's input at `input_index`.
1510    pub fn spend_utxo(&self, input_index: u64) -> String {
1511        let psbt = self.0.lock().unwrap();
1512        let utxo = psbt.spend_utxo(input_index as usize).unwrap();
1513        serde_json::to_string(&utxo).unwrap()
1514    }
1515
1516    /// The corresponding key-value map for each input in the unsigned transaction.
1517    pub fn input(&self) -> Vec<Input> {
1518        let psbt = self.0.lock().unwrap();
1519        psbt.inputs.iter().map(|input| input.into()).collect()
1520    }
1521
1522    /// The corresponding key-value map for each output in the unsigned transaction.
1523    pub fn output(&self) -> Vec<Output> {
1524        let psbt = self.0.lock().unwrap();
1525        psbt.outputs.iter().map(|o| o.into()).collect()
1526    }
1527}
1528
1529impl From<BdkPsbt> for Psbt {
1530    fn from(psbt: BdkPsbt) -> Self {
1531        Psbt(Mutex::new(psbt))
1532    }
1533}
1534
1535#[derive(uniffi::Record)]
1536pub struct FinalizedPsbtResult {
1537    pub psbt: Arc<Psbt>,
1538    pub could_finalize: bool,
1539    pub errors: Option<Vec<PsbtFinalizeError>>,
1540}
1541
1542/// A transcation input.
1543#[derive(Debug, Clone, uniffi::Record)]
1544pub struct TxIn {
1545    /// A pointer to the previous output this input spends from.
1546    pub previous_output: OutPoint,
1547    /// The script corresponding to the `scriptPubKey`, empty in SegWit transactions.
1548    pub script_sig: Arc<Script>,
1549    /// https://bitcoin.stackexchange.com/questions/87372/what-does-the-sequence-in-a-transaction-input-mean
1550    pub sequence: u32,
1551    /// A proof for the script that authorizes the spend of the output.
1552    pub witness: Vec<Vec<u8>>,
1553}
1554
1555impl From<&BdkTxIn> for TxIn {
1556    fn from(tx_in: &BdkTxIn) -> Self {
1557        TxIn {
1558            previous_output: OutPoint {
1559                txid: Arc::new(Txid(tx_in.previous_output.txid)),
1560                vout: tx_in.previous_output.vout,
1561            },
1562            script_sig: Arc::new(Script(tx_in.script_sig.clone())),
1563            sequence: tx_in.sequence.0,
1564            witness: tx_in.witness.to_vec(),
1565        }
1566    }
1567}
1568
1569/// Bitcoin transaction output.
1570///
1571/// Defines new coins to be created as a result of the transaction,
1572/// along with spending conditions ("script", aka "output script"),
1573/// which an input spending it must satisfy.
1574///
1575/// An output that is not yet spent by an input is called Unspent Transaction Output ("UTXO").
1576#[derive(Debug, Clone, uniffi::Record)]
1577pub struct TxOut {
1578    /// The value of the output, in satoshis.
1579    pub value: Arc<Amount>,
1580    /// The script which must be satisfied for the output to be spent.
1581    pub script_pubkey: Arc<Script>,
1582}
1583
1584impl From<&BdkTxOut> for TxOut {
1585    fn from(tx_out: &BdkTxOut) -> Self {
1586        TxOut {
1587            value: Arc::new(Amount(tx_out.value)),
1588            script_pubkey: Arc::new(Script(tx_out.script_pubkey.clone())),
1589        }
1590    }
1591}
1592
1593impl From<BdkTxOut> for TxOut {
1594    fn from(tx_out: BdkTxOut) -> Self {
1595        Self {
1596            value: Arc::new(Amount(tx_out.value)),
1597            script_pubkey: Arc::new(Script(tx_out.script_pubkey)),
1598        }
1599    }
1600}
1601
1602impl From<TxOut> for BdkTxOut {
1603    fn from(tx_out: TxOut) -> Self {
1604        Self {
1605            value: tx_out.value.0,
1606            script_pubkey: tx_out.script_pubkey.0.clone(),
1607        }
1608    }
1609}
1610
1611/// A child number in a derivation path
1612#[derive(Copy, Clone, uniffi::Enum)]
1613pub enum ChildNumber {
1614    /// Non-hardened key
1615    Normal {
1616        /// Key index, within [0, 2^31 - 1]
1617        index: u32,
1618    },
1619    /// Hardened key
1620    Hardened {
1621        /// Key index, within [0, 2^31 - 1]
1622        index: u32,
1623    },
1624}
1625
1626impl From<BdkChildNumber> for ChildNumber {
1627    fn from(value: BdkChildNumber) -> Self {
1628        match value {
1629            BdkChildNumber::Normal { index } => ChildNumber::Normal { index },
1630            BdkChildNumber::Hardened { index } => ChildNumber::Hardened { index },
1631        }
1632    }
1633}
1634
1635impl TryFrom<ChildNumber> for BdkChildNumber {
1636    type Error = Bip32Error;
1637
1638    fn try_from(value: ChildNumber) -> Result<Self, Self::Error> {
1639        match value {
1640            ChildNumber::Normal { index } => {
1641                BdkChildNumber::from_normal_idx(index).map_err(Bip32Error::from)
1642            }
1643            ChildNumber::Hardened { index } => {
1644                BdkChildNumber::from_hardened_idx(index).map_err(Bip32Error::from)
1645            }
1646        }
1647    }
1648}
1649
1650/// A bitcoin Block hash
1651#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1652#[uniffi::export(Display, Eq, Hash, Ord)]
1653pub struct BlockHash(pub(crate) BitcoinBlockHash);
1654
1655impl_hash_like!(BlockHash, BitcoinBlockHash);
1656
1657/// A bitcoin transaction identifier
1658#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1659#[uniffi::export(Display, Eq, Hash, Ord)]
1660pub struct Txid(pub(crate) BitcoinTxid);
1661
1662impl_hash_like!(Txid, BitcoinTxid);
1663
1664/// A bitcoin transaction identifier, including witness data.
1665/// For transactions with no SegWit inputs, the `txid` will be equivalent to `wtxid`.
1666#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1667#[uniffi::export(Display, Eq, Hash, Ord)]
1668pub struct Wtxid(pub(crate) BitcoinWtxid);
1669
1670impl_hash_like!(Wtxid, BitcoinWtxid);
1671
1672/// A collision-proof unique identifier for a descriptor.
1673#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1674#[uniffi::export(Display, Eq, Hash, Ord)]
1675pub struct DescriptorId(pub(crate) BitcoinSha256Hash);
1676
1677impl_hash_like!(DescriptorId, BitcoinSha256Hash);
1678
1679/// The merkle root of the merkle tree corresponding to a block's transactions.
1680#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, std::hash::Hash, uniffi::Object)]
1681#[uniffi::export(Display, Eq, Hash, Ord)]
1682pub struct TxMerkleNode(pub(crate) BitcoinDoubleSha256Hash);
1683
1684impl_hash_like!(TxMerkleNode, BitcoinDoubleSha256Hash);
1685
1686/// Descriptor Type of the descriptor
1687#[uniffi::remote(Enum)]
1688pub enum DescriptorType {
1689    /// Bare descriptor(Contains the native P2pk)
1690    Bare,
1691    /// Pure Sh Descriptor. Does not contain nested Wsh/Wpkh
1692    Sh,
1693    /// Pkh Descriptor
1694    Pkh,
1695    /// Wpkh Descriptor
1696    Wpkh,
1697    /// Wsh
1698    Wsh,
1699    /// Sh Wrapped Wsh
1700    ShWsh,
1701    /// Sh wrapped Wpkh
1702    ShWpkh,
1703    /// Sh Sorted Multi
1704    ShSortedMulti,
1705    /// Wsh Sorted Multi
1706    WshSortedMulti,
1707    /// Sh Wsh Sorted Multi
1708    ShWshSortedMulti,
1709    /// Tr Descriptor
1710    Tr,
1711}