Skip to main content

bitcoin/util/psbt/map/
output.rs

1// Rust Bitcoin Library
2// Written by
3//   The Rust Bitcoin developers
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15use std::io;
16use std::collections::BTreeMap;
17use std::collections::btree_map::Entry;
18
19use blockdata::script::Script;
20use consensus::encode;
21use util::bip32::KeySource;
22use util::key::PublicKey;
23use util::psbt;
24use util::psbt::map::Map;
25use util::psbt::raw;
26use util::psbt::Error;
27
28/// Type: Redeem Script PSBT_OUT_REDEEM_SCRIPT = 0x00
29const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00;
30/// Type: Witness Script PSBT_OUT_WITNESS_SCRIPT = 0x01
31const PSBT_OUT_WITNESS_SCRIPT: u8 = 0x01;
32/// Type: BIP 32 Derivation Path PSBT_OUT_BIP32_DERIVATION = 0x02
33const PSBT_OUT_BIP32_DERIVATION: u8 = 0x02;
34/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC
35const PSBT_OUT_PROPRIETARY: u8 = 0xFC;
36
37/// A key-value map for an output of the corresponding index in the unsigned
38/// transaction.
39#[derive(Clone, Default, Debug, PartialEq)]
40#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
41pub struct Output {
42    /// The redeem script for this output.
43    pub redeem_script: Option<Script>,
44    /// The witness script for this output.
45    pub witness_script: Option<Script>,
46    /// A map from public keys needed to spend this output to their
47    /// corresponding master key fingerprints and derivation paths.
48    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
49    pub bip32_derivation: BTreeMap<PublicKey, KeySource>,
50    /// Proprietary key-value pairs for this output.
51    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
52    pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
53    /// Unknown key-value pairs for this output.
54    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
55    pub unknown: BTreeMap<raw::Key, Vec<u8>>,
56}
57
58impl Map for Output {
59    fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
60        let raw::Pair {
61            key: raw_key,
62            value: raw_value,
63        } = pair;
64
65        match raw_key.type_value {
66            PSBT_OUT_REDEEM_SCRIPT => {
67                impl_psbt_insert_pair! {
68                    self.redeem_script <= <raw_key: _>|<raw_value: Script>
69                }
70            }
71            PSBT_OUT_WITNESS_SCRIPT => {
72                impl_psbt_insert_pair! {
73                    self.witness_script <= <raw_key: _>|<raw_value: Script>
74                }
75            }
76            PSBT_OUT_BIP32_DERIVATION => {
77                impl_psbt_insert_pair! {
78                    self.bip32_derivation <= <raw_key: PublicKey>|<raw_value: KeySource>
79                }
80            }
81            PSBT_OUT_PROPRIETARY => match self.proprietary.entry(raw::ProprietaryKey::from_key(raw_key.clone())?) {
82                Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
83                Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key.clone()).into()),
84            }
85            _ => match self.unknown.entry(raw_key) {
86                    Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
87                    Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()),
88            }
89        }
90
91        Ok(())
92    }
93
94    fn get_pairs(&self) -> Result<Vec<raw::Pair>, io::Error> {
95        let mut rv: Vec<raw::Pair> = Default::default();
96
97        impl_psbt_get_pair! {
98            rv.push(self.redeem_script as <PSBT_OUT_REDEEM_SCRIPT, _>|<Script>)
99        }
100
101        impl_psbt_get_pair! {
102            rv.push(self.witness_script as <PSBT_OUT_WITNESS_SCRIPT, _>|<Script>)
103        }
104
105        impl_psbt_get_pair! {
106            rv.push(self.bip32_derivation as <PSBT_OUT_BIP32_DERIVATION, PublicKey>|<KeySource>)
107        }
108
109        for (key, value) in self.proprietary.iter() {
110            rv.push(raw::Pair {
111                key: key.to_key(),
112                value: value.clone(),
113            });
114        }
115
116        for (key, value) in self.unknown.iter() {
117            rv.push(raw::Pair {
118                key: key.clone(),
119                value: value.clone(),
120            });
121        }
122
123        Ok(rv)
124    }
125
126    fn merge(&mut self, other: Self) -> Result<(), psbt::Error> {
127        self.bip32_derivation.extend(other.bip32_derivation);
128        self.proprietary.extend(other.proprietary);
129        self.unknown.extend(other.unknown);
130
131        merge!(redeem_script, self, other);
132        merge!(witness_script, self, other);
133
134        Ok(())
135    }
136}
137
138impl_psbtmap_consensus_enc_dec_oding!(Output);