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}