bdk_wallet/
types.rs

1// Bitcoin Dev Kit
2// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
3//
4// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
5//
6// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
7// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
9// You may not use this file except in accordance with one or both of these
10// licenses.
11
12use alloc::boxed::Box;
13use chain::{ChainPosition, ConfirmationBlockTime};
14use core::convert::AsRef;
15use core::fmt;
16
17use bitcoin::transaction::{OutPoint, Sequence, TxOut};
18use bitcoin::{psbt, Weight};
19
20use serde::{Deserialize, Serialize};
21
22/// Types of keychains
23#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
24pub enum KeychainKind {
25    /// External keychain, used for deriving recipient addresses.
26    External = 0,
27    /// Internal keychain, used for deriving change addresses.
28    Internal = 1,
29}
30
31impl KeychainKind {
32    /// Return [`KeychainKind`] as a byte
33    pub fn as_byte(&self) -> u8 {
34        match self {
35            KeychainKind::External => b'e',
36            KeychainKind::Internal => b'i',
37        }
38    }
39}
40
41impl fmt::Display for KeychainKind {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        match self {
44            KeychainKind::External => write!(f, "External"),
45            KeychainKind::Internal => write!(f, "Internal"),
46        }
47    }
48}
49
50impl AsRef<[u8]> for KeychainKind {
51    fn as_ref(&self) -> &[u8] {
52        match self {
53            KeychainKind::External => b"e",
54            KeychainKind::Internal => b"i",
55        }
56    }
57}
58
59/// An unspent output owned by a [`Wallet`].
60///
61/// [`Wallet`]: crate::Wallet
62#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
63pub struct LocalOutput {
64    /// Reference to a transaction output
65    pub outpoint: OutPoint,
66    /// Transaction output
67    pub txout: TxOut,
68    /// Type of keychain
69    pub keychain: KeychainKind,
70    /// Whether this UTXO is spent or not
71    pub is_spent: bool,
72    /// The derivation index for the script pubkey in the wallet
73    pub derivation_index: u32,
74    /// The position of the output in the blockchain.
75    pub chain_position: ChainPosition<ConfirmationBlockTime>,
76}
77
78/// A [`Utxo`] with its `satisfaction_weight`.
79#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct WeightedUtxo {
81    /// The weight of the witness data and `scriptSig` expressed in [weight units]. This is used to
82    /// properly maintain the feerate when adding this input to a transaction during coin
83    /// selection.
84    ///
85    /// [weight units]: https://en.bitcoin.it/wiki/Weight_units
86    pub satisfaction_weight: Weight,
87    /// The UTXO
88    pub utxo: Utxo,
89}
90
91#[derive(Debug, Clone, PartialEq, Eq)]
92/// An unspent transaction output (UTXO).
93pub enum Utxo {
94    /// A UTXO owned by the local wallet.
95    Local(LocalOutput),
96    /// A UTXO owned by another wallet.
97    Foreign {
98        /// The location of the output.
99        outpoint: OutPoint,
100        /// The nSequence value to set for this input.
101        sequence: Sequence,
102        /// The information about the input we require to add it to a PSBT.
103        // Box it to stop the type being too big.
104        psbt_input: Box<psbt::Input>,
105    },
106}
107
108impl Utxo {
109    /// Get the location of the UTXO
110    pub fn outpoint(&self) -> OutPoint {
111        match &self {
112            Utxo::Local(local) => local.outpoint,
113            Utxo::Foreign { outpoint, .. } => *outpoint,
114        }
115    }
116
117    /// Get the `TxOut` of the UTXO
118    pub fn txout(&self) -> &TxOut {
119        match &self {
120            Utxo::Local(local) => &local.txout,
121            Utxo::Foreign {
122                outpoint,
123                psbt_input,
124                ..
125            } => {
126                if let Some(prev_tx) = &psbt_input.non_witness_utxo {
127                    return &prev_tx.output[outpoint.vout as usize];
128                }
129
130                if let Some(txout) = &psbt_input.witness_utxo {
131                    return txout;
132                }
133
134                unreachable!("Foreign UTXOs will always have one of these set")
135            }
136        }
137    }
138
139    /// Get the sequence number if an explicit sequence number has to be set for this input.
140    pub fn sequence(&self) -> Option<Sequence> {
141        match self {
142            Utxo::Local(_) => None,
143            Utxo::Foreign { sequence, .. } => Some(*sequence),
144        }
145    }
146}