bitcoin/psbt/map/
output.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use secp256k1::XOnlyPublicKey;
4
5use crate::bip32::KeySource;
6use crate::blockdata::script::ScriptBuf;
7use crate::prelude::*;
8use crate::psbt::map::Map;
9use crate::psbt::{raw, Error};
10use crate::taproot::{TapLeafHash, TapTree};
11
12/// Type: Redeem ScriptBuf PSBT_OUT_REDEEM_SCRIPT = 0x00
13const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00;
14/// Type: Witness ScriptBuf PSBT_OUT_WITNESS_SCRIPT = 0x01
15const PSBT_OUT_WITNESS_SCRIPT: u8 = 0x01;
16/// Type: BIP 32 Derivation Path PSBT_OUT_BIP32_DERIVATION = 0x02
17const PSBT_OUT_BIP32_DERIVATION: u8 = 0x02;
18/// Type: Taproot Internal Key PSBT_OUT_TAP_INTERNAL_KEY = 0x05
19const PSBT_OUT_TAP_INTERNAL_KEY: u8 = 0x05;
20/// Type: Taproot Tree PSBT_OUT_TAP_TREE = 0x06
21const PSBT_OUT_TAP_TREE: u8 = 0x06;
22/// Type: Taproot Key BIP 32 Derivation Path PSBT_OUT_TAP_BIP32_DERIVATION = 0x07
23const PSBT_OUT_TAP_BIP32_DERIVATION: u8 = 0x07;
24/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC
25const PSBT_OUT_PROPRIETARY: u8 = 0xFC;
26
27/// A key-value map for an output of the corresponding index in the unsigned
28/// transaction.
29#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
30#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
31#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
32pub struct Output {
33    /// The redeem script for this output.
34    pub redeem_script: Option<ScriptBuf>,
35    /// The witness script for this output.
36    pub witness_script: Option<ScriptBuf>,
37    /// A map from public keys needed to spend this output to their
38    /// corresponding master key fingerprints and derivation paths.
39    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
40    pub bip32_derivation: BTreeMap<secp256k1::PublicKey, KeySource>,
41    /// The internal pubkey.
42    pub tap_internal_key: Option<XOnlyPublicKey>,
43    /// Taproot Output tree.
44    pub tap_tree: Option<TapTree>,
45    /// Map of tap root x only keys to origin info and leaf hashes contained in it.
46    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
47    pub tap_key_origins: BTreeMap<XOnlyPublicKey, (Vec<TapLeafHash>, KeySource)>,
48    /// Proprietary key-value pairs for this output.
49    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
50    pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
51    /// Unknown key-value pairs for this output.
52    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
53    pub unknown: BTreeMap<raw::Key, Vec<u8>>,
54}
55
56impl Output {
57    pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> {
58        let raw::Pair { key: raw_key, value: raw_value } = pair;
59
60        match raw_key.type_value {
61            PSBT_OUT_REDEEM_SCRIPT => {
62                impl_psbt_insert_pair! {
63                    self.redeem_script <= <raw_key: _>|<raw_value: ScriptBuf>
64                }
65            }
66            PSBT_OUT_WITNESS_SCRIPT => {
67                impl_psbt_insert_pair! {
68                    self.witness_script <= <raw_key: _>|<raw_value: ScriptBuf>
69                }
70            }
71            PSBT_OUT_BIP32_DERIVATION => {
72                impl_psbt_insert_pair! {
73                    self.bip32_derivation <= <raw_key: secp256k1::PublicKey>|<raw_value: KeySource>
74                }
75            }
76            PSBT_OUT_PROPRIETARY => {
77                let key = raw::ProprietaryKey::try_from(raw_key.clone())?;
78                match self.proprietary.entry(key) {
79                    btree_map::Entry::Vacant(empty_key) => {
80                        empty_key.insert(raw_value);
81                    }
82                    btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key)),
83                }
84            }
85            PSBT_OUT_TAP_INTERNAL_KEY => {
86                impl_psbt_insert_pair! {
87                    self.tap_internal_key <= <raw_key: _>|<raw_value: XOnlyPublicKey>
88                }
89            }
90            PSBT_OUT_TAP_TREE => {
91                impl_psbt_insert_pair! {
92                    self.tap_tree <= <raw_key: _>|<raw_value: TapTree>
93                }
94            }
95            PSBT_OUT_TAP_BIP32_DERIVATION => {
96                impl_psbt_insert_pair! {
97                    self.tap_key_origins <= <raw_key: XOnlyPublicKey>|< raw_value: (Vec<TapLeafHash>, KeySource)>
98                }
99            }
100            _ => match self.unknown.entry(raw_key) {
101                btree_map::Entry::Vacant(empty_key) => {
102                    empty_key.insert(raw_value);
103                }
104                btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())),
105            },
106        }
107
108        Ok(())
109    }
110
111    /// Combines this [`Output`] with `other` `Output` (as described by BIP 174).
112    pub fn combine(&mut self, other: Self) {
113        self.bip32_derivation.extend(other.bip32_derivation);
114        self.proprietary.extend(other.proprietary);
115        self.unknown.extend(other.unknown);
116        self.tap_key_origins.extend(other.tap_key_origins);
117
118        combine!(redeem_script, self, other);
119        combine!(witness_script, self, other);
120        combine!(tap_internal_key, self, other);
121        combine!(tap_tree, self, other);
122    }
123}
124
125impl Map for Output {
126    fn get_pairs(&self) -> Vec<raw::Pair> {
127        let mut rv: Vec<raw::Pair> = Default::default();
128
129        impl_psbt_get_pair! {
130            rv.push(self.redeem_script, PSBT_OUT_REDEEM_SCRIPT)
131        }
132
133        impl_psbt_get_pair! {
134            rv.push(self.witness_script, PSBT_OUT_WITNESS_SCRIPT)
135        }
136
137        impl_psbt_get_pair! {
138            rv.push_map(self.bip32_derivation, PSBT_OUT_BIP32_DERIVATION)
139        }
140
141        impl_psbt_get_pair! {
142            rv.push(self.tap_internal_key, PSBT_OUT_TAP_INTERNAL_KEY)
143        }
144
145        impl_psbt_get_pair! {
146            rv.push(self.tap_tree, PSBT_OUT_TAP_TREE)
147        }
148
149        impl_psbt_get_pair! {
150            rv.push_map(self.tap_key_origins, PSBT_OUT_TAP_BIP32_DERIVATION)
151        }
152
153        for (key, value) in self.proprietary.iter() {
154            rv.push(raw::Pair { key: key.to_key(), value: value.clone() });
155        }
156
157        for (key, value) in self.unknown.iter() {
158            rv.push(raw::Pair { key: key.clone(), value: value.clone() });
159        }
160
161        rv
162    }
163}
164
165impl_psbtmap_ser_de_serialize!(Output);