psbt_v2/v0/bitcoin/map/
output.rs1use core::convert::TryFrom;
4
5use bitcoin::bip32::KeySource;
6use bitcoin::blockdata::script::ScriptBuf;
7use bitcoin::key::PublicKey;
8use bitcoin::secp256k1::XOnlyPublicKey;
9use bitcoin::taproot::{TapLeafHash, TapTree};
10
11use crate::prelude::*;
12use crate::v0::bitcoin::map::Map;
13use crate::v0::bitcoin::{raw, Error};
14
15const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00;
17const PSBT_OUT_WITNESS_SCRIPT: u8 = 0x01;
19const PSBT_OUT_BIP32_DERIVATION: u8 = 0x02;
21const PSBT_OUT_TAP_INTERNAL_KEY: u8 = 0x05;
23const PSBT_OUT_TAP_TREE: u8 = 0x06;
25const PSBT_OUT_TAP_BIP32_DERIVATION: u8 = 0x07;
27const PSBT_OUT_AMOUNT: u8 = 0x03;
29const PSBT_OUT_SCRIPT: u8 = 0x04;
31const PSBT_OUT_PROPRIETARY: u8 = 0xFC;
33
34#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)]
37#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
38pub struct Output {
39 pub redeem_script: Option<ScriptBuf>,
41 pub witness_script: Option<ScriptBuf>,
43 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
46 pub bip32_derivation: BTreeMap<PublicKey, KeySource>,
47 pub tap_internal_key: Option<XOnlyPublicKey>,
49 pub tap_tree: Option<TapTree>,
51 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))]
53 pub tap_key_origins: BTreeMap<XOnlyPublicKey, (Vec<TapLeafHash>, KeySource)>,
54 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
56 pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
57 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
59 pub unknown: BTreeMap<raw::Key, Vec<u8>>,
60}
61
62impl Output {
63 pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> {
64 let raw::Pair { key: raw_key, value: raw_value } = pair;
65
66 match raw_key.type_value {
67 PSBT_OUT_REDEEM_SCRIPT => {
68 impl_psbt_insert_pair! {
69 self.redeem_script <= <raw_key: _>|<raw_value: ScriptBuf>
70 }
71 }
72 PSBT_OUT_WITNESS_SCRIPT => {
73 impl_psbt_insert_pair! {
74 self.witness_script <= <raw_key: _>|<raw_value: ScriptBuf>
75 }
76 }
77 PSBT_OUT_BIP32_DERIVATION => {
78 impl_psbt_insert_pair! {
79 self.bip32_derivation <= <raw_key: PublicKey>|<raw_value: KeySource>
80 }
81 }
82 PSBT_OUT_PROPRIETARY => {
83 let key = raw::ProprietaryKey::try_from(raw_key.clone())?;
84 match self.proprietary.entry(key) {
85 btree_map::Entry::Vacant(empty_key) => {
86 empty_key.insert(raw_value);
87 }
88 btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key)),
89 }
90 }
91 PSBT_OUT_TAP_INTERNAL_KEY => {
92 impl_psbt_insert_pair! {
93 self.tap_internal_key <= <raw_key: _>|<raw_value: XOnlyPublicKey>
94 }
95 }
96 PSBT_OUT_TAP_TREE => {
97 impl_psbt_insert_pair! {
98 self.tap_tree <= <raw_key: _>|<raw_value: TapTree>
99 }
100 }
101 PSBT_OUT_TAP_BIP32_DERIVATION => {
102 impl_psbt_insert_pair! {
103 self.tap_key_origins <= <raw_key: XOnlyPublicKey>|< raw_value: (Vec<TapLeafHash>, KeySource)>
104 }
105 }
106 v if v == PSBT_OUT_AMOUNT || v == PSBT_OUT_SCRIPT => {
107 return Err(Error::ExcludedKey { key_type_value: v });
108 }
109 _ => match self.unknown.entry(raw_key) {
110 btree_map::Entry::Vacant(empty_key) => {
111 empty_key.insert(raw_value);
112 }
113 btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())),
114 },
115 }
116
117 Ok(())
118 }
119
120 pub fn combine(&mut self, other: Self) {
122 self.bip32_derivation.extend(other.bip32_derivation);
123 self.proprietary.extend(other.proprietary);
124 self.unknown.extend(other.unknown);
125 self.tap_key_origins.extend(other.tap_key_origins);
126
127 combine!(redeem_script, self, other);
128 combine!(witness_script, self, other);
129 combine!(tap_internal_key, self, other);
130 combine!(tap_tree, self, other);
131 }
132}
133
134impl Map for Output {
135 fn get_pairs(&self) -> Vec<raw::Pair> {
136 let mut rv: Vec<raw::Pair> = Default::default();
137
138 impl_psbt_get_pair! {
139 rv.push(self.redeem_script, PSBT_OUT_REDEEM_SCRIPT)
140 }
141
142 impl_psbt_get_pair! {
143 rv.push(self.witness_script, PSBT_OUT_WITNESS_SCRIPT)
144 }
145
146 impl_psbt_get_pair! {
147 rv.push_map(self.bip32_derivation, PSBT_OUT_BIP32_DERIVATION)
148 }
149
150 impl_psbt_get_pair! {
151 rv.push(self.tap_internal_key, PSBT_OUT_TAP_INTERNAL_KEY)
152 }
153
154 impl_psbt_get_pair! {
155 rv.push(self.tap_tree, PSBT_OUT_TAP_TREE)
156 }
157
158 impl_psbt_get_pair! {
159 rv.push_map(self.tap_key_origins, PSBT_OUT_TAP_BIP32_DERIVATION)
160 }
161
162 for (key, value) in self.proprietary.iter() {
163 rv.push(raw::Pair { key: key.to_key(), value: value.clone() });
164 }
165
166 for (key, value) in self.unknown.iter() {
167 rv.push(raw::Pair { key: key.clone(), value: value.clone() });
168 }
169
170 rv
171 }
172}
173
174impl_psbtmap_ser_de_serialize!(Output);