psbt/
data.rs

1// Modern, minimalistic & standard-compliant cold wallet library.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2020-2024 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2020-2024 LNP/BP Standards Association. All rights reserved.
9// Copyright (C) 2020-2024 Dr Maxim Orlovsky. All rights reserved.
10//
11// Licensed under the Apache License, Version 2.0 (the "License");
12// you may not use this file except in compliance with the License.
13// You may obtain a copy of the License at
14//
15//     http://www.apache.org/licenses/LICENSE-2.0
16//
17// Unless required by applicable law or agreed to in writing, software
18// distributed under the License is distributed on an "AS IS" BASIS,
19// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20// See the License for the specific language governing permissions and
21// limitations under the License.
22
23use std::collections::BTreeSet;
24
25use amplify::num::u5;
26use amplify::{ByteArray, Bytes20, Bytes32};
27use derive::{
28    Bip340Sig, ByteStr, ControlBlock, InternalPk, KeyOrigin, LeafScript, LegacyPk, LegacySig,
29    LockHeight, LockTime, LockTimestamp, Outpoint, RedeemScript, Sats, ScriptCode, ScriptPubkey,
30    SeqNo, SigScript, SighashType, TapDerivation, TapLeafHash, TapNodeHash, TapTree, Terminal, Tx,
31    TxIn, TxOut, TxVer, Txid, VarIntArray, Vout, Witness, WitnessScript, XOnlyPk, XkeyOrigin, Xpub,
32};
33use descriptors::{Descriptor, LegacyKeySig, TaprootKeySig};
34use indexmap::IndexMap;
35
36pub use self::display_from_str::PsbtParseError;
37use crate::{KeyData, PropKey, PsbtError, PsbtVer, ValueData};
38
39#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)]
40#[display("PSBT can't be modified")]
41pub struct Unmodifiable;
42
43#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)]
44#[display(
45    "can't extract signed transaction from PSBT since it still contains {0} non-finalized inputs"
46)]
47pub struct UnfinalizedInputs(pub usize);
48
49#[derive(Copy, Clone, Eq, PartialEq, Debug)]
50pub struct Prevout {
51    pub txid: Txid,
52    pub vout: Vout,
53    pub value: Sats,
54}
55
56impl Prevout {
57    pub fn new(outpoint: Outpoint, value: Sats) -> Self {
58        Prevout {
59            txid: outpoint.txid,
60            vout: outpoint.vout,
61            value,
62        }
63    }
64
65    pub fn outpoint(&self) -> Outpoint { Outpoint::new(self.txid, self.vout) }
66}
67
68/// Structure representing data on unsigned transaction the way it is stored in PSBTv1 global key.
69///
70/// We can't use [`Tx`] since PSBT may contain unsigned transaction with zero inputs, according to
71/// BIP-174 test cases. [`Tx`] containing zero inputs is an invalid structure, prohibited by
72/// consensus. An attempt to deserialize it will be incorrectly identified as a Segwit transaction
73/// (since zero inputs is the trick which was used to make Segwit softfork) and fail with invalid
74/// segwit flag error (since the second byte after 0 segwit indicator must be `01` and not a number
75/// of inputs) fail to parse outputs (for transactions containing just a one output).
76///
77/// `UnsignedTx` also ensures invariant that none of its inputs contain witnesses or sigscripts.
78#[derive(Clone, Eq, PartialEq, Hash, Debug)]
79#[cfg_attr(
80    feature = "strict_encoding",
81    derive(StrictType, StrictDumb, StrictEncode, StrictDecode),
82    strict_type(lib = crate::LIB_NAME_PSBT)
83)]
84#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
85pub struct UnsignedTx {
86    pub version: TxVer,
87    pub inputs: VarIntArray<UnsignedTxIn>,
88    pub outputs: VarIntArray<TxOut>,
89    pub lock_time: LockTime,
90}
91
92impl From<Tx> for UnsignedTx {
93    #[inline]
94    fn from(tx: Tx) -> UnsignedTx { UnsignedTx::with_sigs_removed(tx) }
95}
96
97impl From<UnsignedTx> for Tx {
98    #[inline]
99    fn from(unsigned_tx: UnsignedTx) -> Tx {
100        Tx {
101            version: unsigned_tx.version,
102            inputs: VarIntArray::from_checked(
103                unsigned_tx.inputs.into_iter().map(TxIn::from).collect(),
104            ),
105            outputs: unsigned_tx.outputs,
106            lock_time: unsigned_tx.lock_time,
107        }
108    }
109}
110
111impl UnsignedTx {
112    #[inline]
113    pub fn with_sigs_removed(tx: Tx) -> UnsignedTx {
114        UnsignedTx {
115            version: tx.version,
116            inputs: VarIntArray::from_checked(
117                tx.inputs.into_iter().map(UnsignedTxIn::with_sigs_removed).collect(),
118            ),
119            outputs: tx.outputs,
120            lock_time: tx.lock_time,
121        }
122    }
123
124    pub fn txid(&self) -> Txid { Tx::from(self.clone()).txid() }
125}
126
127#[derive(Clone, Eq, PartialEq, Hash, Debug)]
128#[cfg_attr(
129    feature = "strict_encoding",
130    derive(StrictType, StrictDumb, StrictEncode, StrictDecode),
131    strict_type(lib = crate::LIB_NAME_PSBT)
132)]
133#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
134pub struct UnsignedTxIn {
135    pub prev_output: Outpoint,
136    pub sequence: SeqNo,
137}
138
139impl From<TxIn> for UnsignedTxIn {
140    #[inline]
141    fn from(txin: TxIn) -> UnsignedTxIn { UnsignedTxIn::with_sigs_removed(txin) }
142}
143
144impl From<UnsignedTxIn> for TxIn {
145    #[inline]
146    fn from(unsigned_txin: UnsignedTxIn) -> TxIn {
147        TxIn {
148            prev_output: unsigned_txin.prev_output,
149            sig_script: none!(),
150            sequence: unsigned_txin.sequence,
151            witness: empty!(),
152        }
153    }
154}
155
156impl UnsignedTxIn {
157    #[inline]
158    pub fn with_sigs_removed(txin: TxIn) -> UnsignedTxIn {
159        UnsignedTxIn {
160            prev_output: txin.prev_output,
161            sequence: txin.sequence,
162        }
163    }
164}
165
166#[derive(Clone, Eq, PartialEq, Debug)]
167#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
168// Serde deserialize is not implemented and require manual implementation instead of derive, since
169// we need to correctly initialize inputs and outputs with their indexes and account for unknown
170// fields.
171pub struct Psbt {
172    /// PSBT version
173    pub version: PsbtVer,
174
175    /// Transaction version.
176    pub tx_version: TxVer,
177
178    /// Fallback locktime (used if none of the inputs specifies their locktime).
179    pub fallback_locktime: Option<LockTime>,
180
181    /// The corresponding key-value map for each input.
182    pub(crate) inputs: Vec<Input>,
183
184    /// The corresponding key-value map for each output.
185    pub(crate) outputs: Vec<Output>,
186
187    /// A global map from extended public keys to the used key fingerprint and
188    /// derivation path as defined by BIP 32
189    pub xpubs: IndexMap<Xpub, XkeyOrigin>,
190
191    /// Transaction Modifiable Flags
192    pub(crate) tx_modifiable: Option<ModifiableFlags>,
193
194    /// Proprietary keys
195    pub proprietary: IndexMap<PropKey, ValueData>,
196
197    /// Unknown keys
198    pub unknown: IndexMap<u8, IndexMap<KeyData, ValueData>>,
199}
200
201impl Default for Psbt {
202    fn default() -> Self { Psbt::create(PsbtVer::V2) }
203}
204
205impl Psbt {
206    pub fn create(version: PsbtVer) -> Psbt {
207        Psbt {
208            version,
209            tx_version: TxVer::V2,
210            fallback_locktime: None,
211            inputs: vec![],
212            outputs: vec![],
213            xpubs: none!(),
214            tx_modifiable: Some(ModifiableFlags::modifiable()),
215            proprietary: none!(),
216            unknown: none!(),
217        }
218    }
219
220    pub fn from_tx(tx: impl Into<UnsignedTx>) -> Self {
221        let unsigned_tx = tx.into();
222        let mut psbt = Psbt::create(PsbtVer::V0);
223        psbt.reset_from_unsigned_tx(unsigned_tx);
224        psbt
225    }
226
227    pub(crate) fn reset_from_unsigned_tx(&mut self, unsigned_tx: UnsignedTx) {
228        self.version = PsbtVer::V0;
229        self.tx_version = unsigned_tx.version;
230        self.fallback_locktime = Some(unsigned_tx.lock_time);
231        self.inputs =
232            unsigned_tx.inputs.into_iter().enumerate().map(Input::from_unsigned_txin).collect();
233        self.outputs =
234            unsigned_tx.outputs.into_iter().enumerate().map(Output::from_txout).collect();
235    }
236
237    pub(crate) fn reset_inputs(&mut self, input_count: usize) {
238        self.inputs = (0..input_count).map(Input::new).collect();
239    }
240
241    pub(crate) fn reset_outputs(&mut self, output_count: usize) {
242        self.outputs = (0..output_count).map(Output::new).collect();
243    }
244
245    pub fn to_unsigned_tx(&self) -> UnsignedTx {
246        UnsignedTx {
247            version: self.tx_version,
248            inputs: VarIntArray::from_iter_checked(self.inputs().map(Input::to_unsigned_txin)),
249            outputs: VarIntArray::from_iter_checked(self.outputs().map(Output::to_txout)),
250            lock_time: self.lock_time(),
251        }
252    }
253
254    pub fn txid(&self) -> Txid { self.to_unsigned_tx().txid() }
255
256    pub fn input(&self, index: usize) -> Option<&Input> { self.inputs.get(index) }
257
258    pub fn input_mut(&mut self, index: usize) -> Option<&mut Input> { self.inputs.get_mut(index) }
259
260    pub fn inputs(&self) -> impl Iterator<Item = &Input> { self.inputs.iter() }
261
262    pub fn inputs_mut(&mut self) -> impl Iterator<Item = &mut Input> { self.inputs.iter_mut() }
263
264    pub fn output(&self, index: usize) -> Option<&Output> { self.outputs.get(index) }
265
266    pub fn output_mut(&mut self, index: usize) -> Option<&mut Output> {
267        self.outputs.get_mut(index)
268    }
269
270    pub fn outputs(&self) -> impl Iterator<Item = &Output> { self.outputs.iter() }
271
272    pub fn outputs_mut(&mut self) -> impl Iterator<Item = &mut Output> { self.outputs.iter_mut() }
273
274    pub fn lock_time(&self) -> LockTime {
275        // TODO #45: Compute correct LockTime
276        self.fallback_locktime.unwrap_or(LockTime::ZERO)
277    }
278
279    #[inline]
280    pub fn input_sum(&self) -> Sats { self.inputs().map(Input::value).sum() }
281
282    #[inline]
283    pub fn output_sum(&self) -> Sats { self.outputs().map(Output::value).sum() }
284
285    #[inline]
286    pub fn fee(&self) -> Option<Sats> { self.input_sum().checked_sub(self.output_sum()) }
287
288    pub fn xpubs(&self) -> impl Iterator<Item = (&Xpub, &XkeyOrigin)> { self.xpubs.iter() }
289
290    pub fn is_modifiable(&self) -> bool {
291        self.tx_modifiable.as_ref().map(ModifiableFlags::is_modifiable).unwrap_or_default()
292    }
293
294    pub fn are_inputs_modifiable(&self) -> bool {
295        self.tx_modifiable
296            .as_ref()
297            .map(|flags| flags.inputs_modifiable && !flags.sighash_single)
298            .unwrap_or_default()
299    }
300
301    pub fn are_outputs_modifiable(&self) -> bool {
302        self.tx_modifiable
303            .as_ref()
304            .map(|flags| flags.inputs_modifiable && !flags.sighash_single)
305            .unwrap_or_default()
306    }
307
308    /// # Panics
309    ///
310    /// If the descriptor generates less or more than one script per the provided terminal
311    pub fn append_input<K, D: Descriptor<K>>(
312        &mut self,
313        prevout: Prevout,
314        descriptor: &D,
315        terminal: Terminal,
316        script_pubkey: ScriptPubkey,
317        sequence: SeqNo,
318    ) -> Result<&mut Input, Unmodifiable> {
319        if !self.are_inputs_modifiable() {
320            return Err(Unmodifiable);
321        }
322
323        let script = descriptor
324            .derive(terminal.keychain, terminal.index)
325            .find(|script| script.to_script_pubkey() == script_pubkey)
326            .expect("unable to generate input matching prevout");
327        let input = Input {
328            index: self.inputs.len(),
329            previous_outpoint: prevout.outpoint(),
330            sequence_number: Some(sequence),
331            required_time_lock: None,
332            required_height_lock: None,
333            non_witness_tx: None,
334            witness_utxo: Some(TxOut::new(script.to_script_pubkey(), prevout.value)),
335            partial_sigs: none!(),
336            sighash_type: None,
337            redeem_script: script.to_redeem_script(),
338            witness_script: script.to_witness_script(),
339            bip32_derivation: descriptor.legacy_keyset(terminal),
340            // TODO #36: Fill hash preimages from descriptor
341            final_script_sig: None,
342            final_witness: None,
343            proof_of_reserves: None,
344            ripemd160: none!(),
345            sha256: none!(),
346            hash160: none!(),
347            hash256: none!(),
348            tap_key_sig: None,
349            tap_script_sig: none!(),
350            tap_leaf_script: script.to_leaf_scripts(),
351            tap_bip32_derivation: descriptor.xonly_keyset(terminal),
352            tap_internal_key: script.to_internal_pk(),
353            tap_merkle_root: script.to_tap_root(),
354            proprietary: none!(),
355            unknown: none!(),
356        };
357        self.inputs.push(input);
358        Ok(self.inputs.last_mut().expect("just inserted"))
359    }
360
361    pub fn append_input_expect<K, D: Descriptor<K>>(
362        &mut self,
363        prevout: Prevout,
364        descriptor: &D,
365        terminal: Terminal,
366        script_pubkey: ScriptPubkey,
367        sequence: SeqNo,
368    ) -> &mut Input {
369        self.append_input(prevout, descriptor, terminal, script_pubkey, sequence)
370            .expect("PSBT inputs are expected to be modifiable")
371    }
372
373    pub fn insert_output(
374        &mut self,
375        pos: usize,
376        script_pubkey: ScriptPubkey,
377        value: Sats,
378    ) -> Result<&mut Output, Unmodifiable> {
379        if !self.are_outputs_modifiable() {
380            return Err(Unmodifiable);
381        }
382
383        let output = Output {
384            amount: value,
385            script: script_pubkey,
386            ..Output::new(pos)
387        };
388        self.outputs.insert(pos, output);
389        for no in pos..self.outputs.len() {
390            self.outputs[no].index = no;
391        }
392        Ok(&mut self.outputs[pos])
393    }
394
395    pub fn append_output(
396        &mut self,
397        script_pubkey: ScriptPubkey,
398        value: Sats,
399    ) -> Result<&mut Output, Unmodifiable> {
400        self.insert_output(self.outputs.len(), script_pubkey, value)
401    }
402
403    pub fn append_output_expect(
404        &mut self,
405        script_pubkey: ScriptPubkey,
406        value: Sats,
407    ) -> &mut Output {
408        self.append_output(script_pubkey, value)
409            .expect("PSBT outputs are expected to be modifiable")
410    }
411
412    /// # Panics
413    ///
414    /// If the descriptor generates less or more than one script per the provided terminal
415    pub fn append_change<K, D: Descriptor<K>>(
416        &mut self,
417        descriptor: &D,
418        change_terminal: Terminal,
419        value: Sats,
420    ) -> Result<&mut Output, Unmodifiable> {
421        if !self.are_outputs_modifiable() {
422            return Err(Unmodifiable);
423        }
424
425        let script = descriptor
426            .derive(change_terminal.keychain, change_terminal.index)
427            .next()
428            .expect("unable to generate change script");
429        let output = Output {
430            index: self.outputs.len(),
431            amount: value,
432            script: script.to_script_pubkey(),
433            redeem_script: script.to_redeem_script(),
434            witness_script: script.to_witness_script(),
435            bip32_derivation: descriptor.legacy_keyset(change_terminal),
436            tap_internal_key: script.to_internal_pk(),
437            tap_tree: script.to_tap_tree(),
438            tap_bip32_derivation: descriptor.xonly_keyset(change_terminal),
439            proprietary: none!(),
440            unknown: none!(),
441        };
442        self.outputs.push(output);
443        Ok(self.outputs.last_mut().expect("just inserted"))
444    }
445
446    pub fn append_change_expect<K, D: Descriptor<K>>(
447        &mut self,
448        descriptor: &D,
449        change_terminal: Terminal,
450        value: Sats,
451    ) -> &mut Output {
452        self.append_change(descriptor, change_terminal, value)
453            .expect("PSBT outputs are expected to be modifiable")
454    }
455
456    pub fn sort_outputs_by<K: Ord>(
457        &mut self,
458        f: impl FnMut(&Output) -> K,
459    ) -> Result<(), Unmodifiable> {
460        if !self.are_outputs_modifiable() {
461            return Err(Unmodifiable);
462        }
463
464        self.outputs.sort_by_key(f);
465        for (index, output) in self.outputs.iter_mut().enumerate() {
466            output.index = index;
467        }
468
469        Ok(())
470    }
471
472    pub fn complete_construction(&mut self) {
473        // TODO #47: Check all inputs have witness_utxo or non_witness_tx
474        self.tx_modifiable = Some(ModifiableFlags::unmodifiable())
475    }
476
477    pub fn is_finalized(&self) -> bool { self.inputs.iter().all(Input::is_finalized) }
478
479    pub fn finalize<D: Descriptor<K, V>, K, V>(&mut self, descriptor: &D) -> usize {
480        self.inputs.iter_mut().map(|input| input.finalize(descriptor) as usize).sum()
481    }
482
483    pub fn extract(&self) -> Result<Tx, UnfinalizedInputs> {
484        let finalized = self.inputs.iter().filter(|i| i.is_finalized()).count();
485        let unfinalized = self.inputs.len() - finalized;
486        if unfinalized > 0 {
487            return Err(UnfinalizedInputs(unfinalized));
488        }
489
490        Ok(Tx {
491            version: self.tx_version,
492            inputs: VarIntArray::from_iter_checked(self.inputs.iter().map(Input::to_signed_txin)),
493            outputs: VarIntArray::from_iter_checked(self.outputs.iter().map(Output::to_txout)),
494            lock_time: self.lock_time(),
495        })
496    }
497}
498
499mod display_from_str {
500    use std::fmt::{self, Display, Formatter, LowerHex};
501    use std::str::FromStr;
502
503    use amplify::hex::{self, FromHex, ToHex};
504    use base64::display::Base64Display;
505    use base64::prelude::BASE64_STANDARD;
506    use base64::Engine;
507
508    use super::*;
509
510    #[derive(Clone, Debug, Display, Error, From)]
511    #[display(inner)]
512    pub enum PsbtParseError {
513        #[from]
514        Hex(hex::Error),
515
516        #[from]
517        Base64(base64::DecodeError),
518
519        #[from]
520        Psbt(PsbtError),
521    }
522
523    impl Psbt {
524        pub fn from_base64(s: &str) -> Result<Psbt, PsbtParseError> {
525            Psbt::deserialize(BASE64_STANDARD.decode(s)?).map_err(PsbtParseError::from)
526        }
527
528        pub fn from_base16(s: &str) -> Result<Psbt, PsbtParseError> {
529            let data = Vec::<u8>::from_hex(s)?;
530            Psbt::deserialize(data).map_err(PsbtParseError::from)
531        }
532
533        pub fn to_base64(&self) -> String { self.to_base64_ver(self.version) }
534
535        pub fn to_base64_ver(&self, version: PsbtVer) -> String {
536            BASE64_STANDARD.encode(self.serialize(version))
537        }
538
539        pub fn to_base16(&self) -> String { self.to_base16_ver(self.version) }
540
541        pub fn to_base16_ver(&self, version: PsbtVer) -> String { self.serialize(version).to_hex() }
542    }
543
544    /// FromStr implementation parses both Base64 and Hex (Base16) encodings.
545    impl FromStr for Psbt {
546        type Err = PsbtParseError;
547
548        #[inline]
549        fn from_str(s: &str) -> Result<Self, Self::Err> {
550            Self::from_base16(s).or_else(|_| Self::from_base64(s))
551        }
552    }
553
554    /// PSBT displays Base64-encoded string. The selection of the version if the following:
555    /// - by default, it uses version specified in the PSBT itself;
556    /// - if zero `{:0}` is given and no width (`{:0}`) or a zero width (`{:00}`) is provided, than
557    ///   the PSBT is encoded as V0 even if the structure itself uses V2;
558    /// - if a width equal to one is given like in `{:1}`, than zero flag is ignored (so `{:01}`
559    ///   also works that way) and PSBT is encoded as V0 even if the structure itself uses V2;
560    /// - if a width equal to two is given like in `{:2}`, than zero flag is ignored (so `{:02}`
561    ///   also works that way) and PSBT is encoded as V2 even if the structure itself uses V1;
562    /// - all other flags has no effect on the display.
563    impl Display for Psbt {
564        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
565            let ver = match (f.width(), f.sign_aware_zero_pad()) {
566                (None, true) => PsbtVer::V0,
567                (Some(1), _) => PsbtVer::V0,
568                (Some(ver), _) => PsbtVer::try_from(ver).map_err(|_| fmt::Error)?,
569                _ => self.version,
570            };
571            write!(f, "{}", Base64Display::new(&self.serialize(ver), &BASE64_STANDARD))
572        }
573    }
574
575    /// PSBT is formatted like hex-encoded string. The selection of the version if the following:
576    /// - by default, it uses version specified in the PSBT itself;
577    /// - if zero `{:0}` is given and no width (`{:0}`) or a zero width (`{:00}`) is provided, than
578    ///   the PSBT is encoded as V0 even if the structure itself uses V2;
579    /// - if a width equal to one is given like in `{:1}`, than zero flag is ignored (so `{:01}`
580    ///   also works that way) and PSBT is encoded as V0 even if the structure itself uses V2;
581    /// - if a width equal to two is given like in `{:2}`, than zero flag is ignored (so `{:02}`
582    ///   also works that way) and PSBT is encoded as V2 even if the structure itself uses V1;
583    /// - all other flags has no effect on the display.
584    impl LowerHex for Psbt {
585        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
586            let ver = match (f.width(), f.sign_aware_zero_pad()) {
587                (None, true) => PsbtVer::V0,
588                (Some(1), _) => PsbtVer::V0,
589                (Some(ver), _) => PsbtVer::try_from(ver).map_err(|_| fmt::Error)?,
590                _ => self.version,
591            };
592            f.write_str(&self.to_base16_ver(ver))
593        }
594    }
595}
596
597/* TODO #43: Complete weight implementation
598impl Weight for Psbt {
599    fn weight_units(&self) -> WeightUnits {
600        let bytes = 4 // version
601            + VarInt::with(self.inputs.len()).len()
602            + VarInt::with(self.outputs.len()).len()
603            + 4; // lock time
604        let mut weight = WeightUnits::no_discount(bytes)
605            + self.inputs().map(TxIn::weight_units).sum()
606            + self.outputs().map(TxOut::weight_units).sum();
607        if self.is_segwit() {
608            weight += WeightUnits::witness_discount(2); // marker and flag bytes
609        }
610        weight
611    }
612}
613 */
614
615#[derive(Clone, Eq, PartialEq, Debug)]
616#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
617pub struct Input {
618    /// The index of this input. Used in error reporting.
619    #[cfg_attr(feature = "serde", serde(skip))]
620    pub(crate) index: usize,
621
622    /// Previous transaction outpoint to spent.
623    pub previous_outpoint: Outpoint,
624
625    /// Sequence number of this input. If omitted, the sequence number is
626    /// assumed to be the final sequence number (0xffffffff).
627    pub sequence_number: Option<SeqNo>,
628
629    /// 32 bit unsigned little endian integer greater than or equal to 500000000
630    /// representing the minimum Unix timestamp that this input requires to be
631    /// set as the transaction's lock time.
632    pub required_time_lock: Option<LockTimestamp>,
633
634    /// 32 bit unsigned little endian integer less than 500000000 representing
635    /// the minimum block height that this input requires to be set as the
636    /// transaction's lock time.
637    pub required_height_lock: Option<LockHeight>,
638
639    /// The non-witness transaction this input spends from. Should only be
640    /// `Some` for inputs which spend non-segwit outputs or if it is unknown
641    /// whether an input spends a segwit output.
642    pub non_witness_tx: Option<Tx>,
643
644    /// The transaction output this input spends from. Should only be `Some` for
645    /// inputs which spend segwit outputs, including P2SH embedded ones.
646    pub witness_utxo: Option<TxOut>,
647
648    /// A map from public keys to their corresponding signature as would be
649    /// pushed to the stack from a scriptSig or witness for a non-taproot
650    /// inputs.
651    pub partial_sigs: IndexMap<LegacyPk, LegacySig>,
652
653    /// The sighash type to be used for this input. Signatures for this input
654    /// must use the sighash type.
655    pub sighash_type: Option<SighashType>,
656
657    /// The redeem script for this input.
658    pub redeem_script: Option<RedeemScript>,
659
660    /// The witness script for this input.
661    pub witness_script: Option<WitnessScript>,
662
663    /// A map from public keys needed to sign this input to their corresponding master key
664    /// fingerprints and derivation paths.
665    pub bip32_derivation: IndexMap<LegacyPk, KeyOrigin>,
666
667    /// The finalized, fully-constructed scriptSig with signatures and any other scripts necessary
668    /// for this input to pass validation.
669    pub final_script_sig: Option<SigScript>,
670
671    /// The finalized, fully-constructed scriptWitness with signatures and any other scripts
672    /// necessary for this input to pass validation.
673    pub final_witness: Option<Witness>,
674
675    /// The UTF-8 encoded commitment message string for the proof-of-reserves. See BIP 127 for more
676    /// information.
677    pub proof_of_reserves: Option<String>,
678
679    ///  The hash preimage, encoded as a byte vector, which must equal the key when run through the
680    /// RIPEMD160 algorithm.
681    pub ripemd160: IndexMap<Bytes20, ByteStr>,
682
683    ///  The hash preimage, encoded as a byte vector, which must equal the key when run through the
684    /// SHA256 algorithm.
685    pub sha256: IndexMap<Bytes32, ByteStr>,
686
687    /// The hash preimage, encoded as a byte vector, which must equal the key when run through the
688    /// SHA256 algorithm followed by the RIPEMD160 algorithm .
689    pub hash160: IndexMap<Bytes20, ByteStr>,
690
691    /// The hash preimage, encoded as a byte vector, which must equal the key when run through the
692    /// SHA256 algorithm twice.
693    pub hash256: IndexMap<Bytes32, ByteStr>,
694
695    /// The 64 or 65 byte Schnorr signature for key path spending a Taproot output. Finalizers
696    /// should remove this field after `PSBT_IN_FINAL_SCRIPTWITNESS` is constructed.
697    pub tap_key_sig: Option<Bip340Sig>,
698
699    /// The 64 or 65 byte Schnorr signature for this pubkey and leaf combination. Finalizers
700    /// should remove this field after `PSBT_IN_FINAL_SCRIPTWITNESS` is constructed.
701    pub tap_script_sig: IndexMap<(XOnlyPk, TapLeafHash), Bip340Sig>,
702
703    /// The script for this leaf as would be provided in the witness stack followed by the single
704    /// byte leaf version. Note that the leaves included in this field should be those that the
705    /// signers of this input are expected to be able to sign for. Finalizers should remove this
706    /// field after `PSBT_IN_FINAL_SCRIPTWITNESS` is constructed.
707    pub tap_leaf_script: IndexMap<ControlBlock, LeafScript>,
708
709    /// A compact size unsigned integer representing the number of leaf hashes, followed by a list
710    /// of leaf hashes, followed by the 4 byte master key fingerprint concatenated with the
711    /// derivation path of the public key. The derivation path is represented as 32-bit little
712    /// endian unsigned integer indexes concatenated with each other. Public keys are those needed
713    /// to spend this output. The leaf hashes are of the leaves which involve this public key. The
714    /// internal key does not have leaf hashes, so can be indicated with a hashes len of 0.
715    /// Finalizers should remove this field after `PSBT_IN_FINAL_SCRIPTWITNESS` is constructed.
716    pub tap_bip32_derivation: IndexMap<XOnlyPk, TapDerivation>,
717
718    /// The X-only pubkey used as the internal key in this output. Finalizers should remove this
719    /// field after `PSBT_IN_FINAL_SCRIPTWITNESS` is constructed.
720    pub tap_internal_key: Option<InternalPk>,
721
722    ///  The 32 byte Merkle root hash. Finalizers should remove this field after
723    /// `PSBT_IN_FINAL_SCRIPTWITNESS` is constructed.
724    pub tap_merkle_root: Option<TapNodeHash>,
725
726    /// Proprietary keys
727    pub proprietary: IndexMap<PropKey, ValueData>,
728
729    /// Unknown keys
730    pub unknown: IndexMap<u8, IndexMap<KeyData, ValueData>>,
731}
732
733impl Input {
734    pub fn new(index: usize) -> Input {
735        Input {
736            index,
737            previous_outpoint: Outpoint::coinbase(),
738            sequence_number: None,
739            required_time_lock: None,
740            required_height_lock: None,
741            non_witness_tx: None,
742            witness_utxo: None,
743            partial_sigs: none!(),
744            sighash_type: None,
745            redeem_script: None,
746            witness_script: None,
747            bip32_derivation: none!(),
748            final_script_sig: None,
749            final_witness: None,
750            proof_of_reserves: None,
751            ripemd160: none!(),
752            sha256: none!(),
753            hash160: none!(),
754            hash256: none!(),
755            tap_key_sig: None,
756            tap_script_sig: none!(),
757            tap_leaf_script: none!(),
758            tap_bip32_derivation: none!(),
759            tap_internal_key: None,
760            tap_merkle_root: None,
761            proprietary: none!(),
762            unknown: none!(),
763        }
764    }
765
766    pub fn with_txin(txin: impl Into<UnsignedTxIn>, index: usize) -> Input {
767        let txin = txin.into();
768        let mut input = Input::new(index);
769        input.previous_outpoint = txin.prev_output;
770        input.sequence_number = Some(txin.sequence);
771        input
772    }
773
774    pub fn from_unsigned_txin((index, txin): (usize, UnsignedTxIn)) -> Input {
775        Input::with_txin(txin, index)
776    }
777
778    fn to_signed_txin(&self) -> TxIn {
779        TxIn {
780            prev_output: self.previous_outpoint,
781            // TODO #45: Figure out default SeqNo
782            sig_script: self.final_script_sig.clone().expect("non-finalized input"),
783            sequence: self.sequence_number.unwrap_or(SeqNo::from_consensus_u32(0)),
784            witness: self.final_witness.clone().expect("non-finalized input"),
785        }
786    }
787
788    pub fn to_unsigned_txin(&self) -> UnsignedTxIn {
789        UnsignedTxIn {
790            prev_output: self.previous_outpoint,
791            // TODO #45: Figure out default SeqNo
792            sequence: self.sequence_number.unwrap_or(SeqNo::from_consensus_u32(0)),
793        }
794    }
795
796    #[inline]
797    pub fn prev_txout(&self) -> &TxOut {
798        // TODO #48: Add support for nonwitness_utxo
799        match (&self.witness_utxo, None::<&Tx>) {
800            (Some(txout), _) => txout,
801            (None, Some(tx)) => &tx.outputs[self.index],
802            (None, None) => unreachable!(
803                "PSBT input must contain either witness UTXO or a non-witness transaction"
804            ),
805        }
806    }
807
808    #[inline]
809    pub fn prevout(&self) -> Prevout {
810        Prevout {
811            txid: self.previous_outpoint.txid,
812            vout: self.previous_outpoint.vout,
813            value: self.value(),
814        }
815    }
816
817    #[inline]
818    pub fn value(&self) -> Sats { self.prev_txout().value }
819
820    #[inline]
821    pub fn index(&self) -> usize { self.index }
822
823    /// Computes script code, used in SegWit v0 signing algorithm (BIP143).
824    ///
825    /// NB: Does not support processing of `OP_CODESEPARATOR`.
826    ///
827    /// # Returns
828    ///
829    /// `None` if input spends P2WSH or P2WSH-in-P2SH output, but contains no witness script.
830    pub fn script_code(&self) -> Option<ScriptCode> {
831        let spk = &self.prev_txout().script_pubkey;
832        Some(match (&self.witness_script, &self.redeem_script) {
833            (None, None) if spk.is_p2wpkh() => ScriptCode::with_p2wpkh(spk),
834            (Some(witness_script), None) if spk.is_p2wsh() => {
835                ScriptCode::with_p2wsh(witness_script)
836            }
837            (_, Some(redeem_script)) if redeem_script.is_p2sh_wpkh() => {
838                ScriptCode::with_p2sh_wpkh(spk)
839            }
840            (Some(witness_script), Some(redeem_script)) if redeem_script.is_p2sh_wsh() => {
841                ScriptCode::with_p2sh_wsh(witness_script)
842            }
843            _ => return None,
844        })
845    }
846
847    #[inline]
848    pub fn is_segwit_v0(&self) -> bool {
849        self.witness_script.is_some()
850            || self.witness_utxo.is_some()
851            || self.prev_txout().script_pubkey.is_p2wpkh()
852            || self.prev_txout().script_pubkey.is_p2wsh()
853    }
854
855    #[must_use]
856    pub fn is_bip340(&self) -> bool { self.tap_internal_key.is_some() }
857
858    #[must_use]
859    pub fn is_finalized(&self) -> bool {
860        self.final_witness.is_some() || self.final_script_sig.is_some()
861    }
862
863    pub fn finalize<D: Descriptor<K, V>, K, V>(&mut self, descriptor: &D) -> bool {
864        if self.is_finalized() {
865            return false;
866        }
867
868        let satisfaction = if descriptor.is_taproot() {
869            self.tap_internal_key
870                .map(XOnlyPk::from)
871                .and_then(|pk| self.tap_bip32_derivation.get(&pk).map(|d| (&d.origin, pk)))
872                .zip(self.tap_key_sig)
873                .and_then(|((origin, pk), sig)| {
874                    // First, we try key path
875                    descriptor.taproot_witness(map! { origin => TaprootKeySig::new(pk, sig) })
876                })
877                .or_else(|| {
878                    // If we can't satisfy key path, we try script paths until we succeed
879                    self.tap_leaf_script
880                        .keys()
881                        .filter_map(|cb| cb.merkle_branch.first())
882                        .copied()
883                        .map(|hash| TapLeafHash::from_byte_array(hash.to_byte_array()))
884                        .find_map(|leafhash| {
885                            let keysigs = self
886                                .tap_script_sig
887                                .iter()
888                                .filter(|((_, lh), _)| *lh == leafhash)
889                                .map(|((pk, _), sig)| TaprootKeySig::new(*pk, *sig))
890                                .filter_map(|ks| {
891                                    self.tap_bip32_derivation
892                                        .get(&ks.key)
893                                        .filter(|d| d.leaf_hashes.contains(&leafhash))
894                                        .map(|d| (&d.origin, ks))
895                                })
896                                .collect();
897                            descriptor.taproot_witness(keysigs)
898                        })
899                })
900                .map(|witness| (empty!(), witness))
901        } else {
902            let keysigs = self
903                .partial_sigs
904                .iter()
905                .map(|(pk, sig)| LegacyKeySig::new(*pk, *sig))
906                .filter_map(|ks| self.bip32_derivation.get(&ks.key).map(|origin| (origin, ks)))
907                .collect();
908            descriptor.legacy_witness(keysigs)
909        };
910        let Some((sig_script, witness)) = satisfaction else {
911            return false;
912        };
913
914        self.final_script_sig = Some(sig_script);
915        self.final_witness = Some(witness);
916        // reset everything
917        self.partial_sigs.clear(); // 0x02
918        self.sighash_type = None; // 0x03
919        self.redeem_script = None; // 0x04
920        self.witness_script = None; // 0x05
921        self.bip32_derivation.clear(); // 0x05
922                                       // finalized witness 0x06 and 0x07 are not clear
923                                       // 0x09 Proof of reserves not yet supported
924        self.ripemd160.clear(); // 0x0a
925        self.sha256.clear(); // 0x0b
926        self.hash160.clear(); // 0x0c
927        self.hash256.clear(); // 0x0d
928                              // psbt v2 fields till 0x012 not supported
929        self.tap_key_sig = None; // 0x013
930        self.tap_script_sig.clear(); // 0x014
931        self.tap_leaf_script.clear(); // 0x015
932        self.tap_bip32_derivation.clear(); // 0x16
933        self.tap_internal_key = None; // x017
934        self.tap_merkle_root = None; // 0x018
935
936        true
937    }
938}
939
940#[derive(Clone, Eq, PartialEq, Debug)]
941#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))]
942pub struct Output {
943    /// The index of this output. Used in error reporting.
944    #[cfg_attr(feature = "serde", serde(skip))]
945    pub(crate) index: usize,
946
947    /// The output's amount in satoshis.
948    pub amount: Sats,
949
950    /// The script for this output, also known as the scriptPubKey.
951    pub script: ScriptPubkey,
952
953    /// The redeem script for this output.
954    pub redeem_script: Option<RedeemScript>,
955
956    /// The witness script for this output.
957    pub witness_script: Option<WitnessScript>,
958
959    /// A map from public keys needed to spend this output to their corresponding master key
960    /// fingerprints and derivation paths.
961    pub bip32_derivation: IndexMap<LegacyPk, KeyOrigin>,
962
963    /// The X-only pubkey used as the internal key in this output.
964    // TODO #49: Add taproot data structures: TapTree and derivation info
965    pub tap_internal_key: Option<InternalPk>,
966
967    /// One or more tuples representing the depth, leaf version, and script for a leaf in the
968    /// Taproot tree, allowing the entire tree to be reconstructed. The tuples must be in depth
969    /// first search order so that the tree is correctly reconstructed. Each tuple is an 8-bit
970    /// unsigned integer representing the depth in the Taproot tree for this script, an 8-bit
971    /// unsigned integer representing the leaf version, the length of the script as a compact size
972    /// unsigned integer, and the script itself.
973    pub tap_tree: Option<TapTree>,
974
975    /// A compact size unsigned integer representing the number of leaf hashes, followed by a list
976    /// of leaf hashes, followed by the 4 byte master key fingerprint concatenated with the
977    /// derivation path of the public key. The derivation path is represented as 32-bit little
978    /// endian unsigned integer indexes concatenated with each other. Public keys are those needed
979    /// to spend this output. The leaf hashes are of the leaves which involve this public key. The
980    /// internal key does not have leaf hashes, so can be indicated with a hashes len of 0.
981    /// Finalizers should remove this field after `PSBT_IN_FINAL_SCRIPTWITNESS` is constructed.
982    pub tap_bip32_derivation: IndexMap<XOnlyPk, TapDerivation>,
983
984    /// Proprietary keys
985    pub proprietary: IndexMap<PropKey, ValueData>,
986
987    /// Unknown keys
988    pub unknown: IndexMap<u8, IndexMap<KeyData, ValueData>>,
989}
990
991impl Output {
992    pub fn new(index: usize) -> Self {
993        Output {
994            index,
995            amount: Sats::ZERO,
996            script: ScriptPubkey::new(),
997            redeem_script: None,
998            witness_script: None,
999            bip32_derivation: none!(),
1000            tap_internal_key: None,
1001            tap_tree: None,
1002            tap_bip32_derivation: none!(),
1003            proprietary: none!(),
1004            unknown: none!(),
1005        }
1006    }
1007
1008    pub fn with_txout(txout: TxOut, index: usize) -> Self {
1009        let mut output = Output::new(index);
1010        output.amount = txout.value;
1011        output.script = txout.script_pubkey;
1012        output
1013    }
1014
1015    pub fn from_txout((index, txout): (usize, TxOut)) -> Self { Output::with_txout(txout, index) }
1016
1017    pub fn to_txout(&self) -> TxOut {
1018        TxOut {
1019            value: self.amount,
1020            script_pubkey: self.script.clone(),
1021        }
1022    }
1023
1024    #[inline]
1025    pub fn value(&self) -> Sats { self.amount }
1026
1027    #[inline]
1028    pub fn index(&self) -> usize { self.index }
1029
1030    #[inline]
1031    pub fn vout(&self) -> Vout { Vout::from_u32(self.index as u32) }
1032
1033    pub fn terminal_derivation(&self) -> Option<Terminal> {
1034        if self.bip32_derivation.is_empty() && self.tap_bip32_derivation.is_empty() {
1035            return None;
1036        }
1037        let terminal = self
1038            .bip32_derivation
1039            .values()
1040            .flat_map(|origin| origin.derivation().terminal())
1041            .chain(
1042                self.tap_bip32_derivation
1043                    .values()
1044                    .flat_map(|derivation| derivation.origin.derivation().terminal()),
1045            )
1046            .collect::<BTreeSet<_>>();
1047        if terminal.len() != 1 {
1048            return None;
1049        }
1050        terminal.first().copied()
1051    }
1052}
1053
1054#[derive(Clone, Eq, PartialEq, Hash, Debug)]
1055#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(rename_all = "camelCase"))]
1056pub struct ModifiableFlags {
1057    pub inputs_modifiable: bool,
1058    pub outputs_modifiable: bool,
1059    pub sighash_single: bool,
1060    pub unknown: u5,
1061}
1062
1063impl ModifiableFlags {
1064    pub const fn unmodifiable() -> Self {
1065        ModifiableFlags {
1066            inputs_modifiable: false,
1067            outputs_modifiable: false,
1068            sighash_single: false,
1069            unknown: u5::ZERO,
1070        }
1071    }
1072
1073    pub const fn modifiable() -> Self {
1074        ModifiableFlags {
1075            inputs_modifiable: true,
1076            outputs_modifiable: true,
1077            sighash_single: false,
1078            unknown: u5::ZERO,
1079        }
1080    }
1081
1082    pub const fn modifiable_sighash_single() -> Self {
1083        ModifiableFlags {
1084            inputs_modifiable: true,
1085            outputs_modifiable: true,
1086            sighash_single: true,
1087            unknown: u5::ZERO,
1088        }
1089    }
1090
1091    pub fn from_standard_u8(val: u8) -> Self {
1092        let inputs_modifiable = val & 0x01 == 0x01;
1093        let outputs_modifiable = val & 0x02 == 0x02;
1094        let sighash_single = val & 0x04 == 0x04;
1095        let unknown = u5::with(val >> 3);
1096        Self {
1097            inputs_modifiable,
1098            outputs_modifiable,
1099            sighash_single,
1100            unknown,
1101        }
1102    }
1103
1104    pub const fn to_standard_u8(&self) -> u8 {
1105        (self.inputs_modifiable as u8)
1106            | ((self.outputs_modifiable as u8) << 1)
1107            | ((self.sighash_single as u8) << 2)
1108    }
1109
1110    pub const fn is_modifiable(&self) -> bool {
1111        self.inputs_modifiable | self.outputs_modifiable | self.sighash_single
1112    }
1113}
1114
1115#[cfg(test)]
1116mod tests {
1117    use super::*;
1118
1119    #[test]
1120    fn psbt_formats() {
1121        let v0_psbt = Psbt {
1122            version: PsbtVer::V0,
1123            tx_version: TxVer::default(),
1124            fallback_locktime: None,
1125            inputs: Vec::new(),
1126            outputs: Vec::new(),
1127            xpubs: IndexMap::new(),
1128            tx_modifiable: None,
1129            proprietary: IndexMap::new(),
1130            unknown: IndexMap::new(),
1131        };
1132        let v2_psbt = Psbt {
1133            version: PsbtVer::V2,
1134            tx_version: TxVer::default(),
1135            fallback_locktime: None,
1136            inputs: Vec::new(),
1137            outputs: Vec::new(),
1138            xpubs: IndexMap::new(),
1139            tx_modifiable: None,
1140            proprietary: IndexMap::new(),
1141            unknown: IndexMap::new(),
1142        };
1143
1144        assert_eq!(format!("{v0_psbt}"), "cHNidP8BAAoCAAAAAAAAAAAAAfsEAAAAAAA=");
1145        assert_eq!(format!("{v2_psbt}"), "cHNidP8BAgQCAAAAAQQBAAEFAQAB+wQCAAAAAA==");
1146
1147        assert_eq!(format!("{v0_psbt:#}"), "cHNidP8BAAoCAAAAAAAAAAAAAfsEAAAAAAA=");
1148        assert_eq!(format!("{v2_psbt:#}"), "cHNidP8BAgQCAAAAAQQBAAEFAQAB+wQCAAAAAA==");
1149
1150        assert_eq!(format!("{v0_psbt:x}"), "70736274ff01000a0200000000000000000001fb040000000000");
1151        assert_eq!(
1152            format!("{v2_psbt:x}"),
1153            "70736274ff01020402000000010401000105010001fb040200000000"
1154        );
1155
1156        assert_eq!(format!("{v0_psbt:#x}"), "70736274ff01000a0200000000000000000001fb040000000000");
1157        assert_eq!(
1158            format!("{v2_psbt:#x}"),
1159            "70736274ff01020402000000010401000105010001fb040200000000"
1160        );
1161
1162        // format with a specific version
1163        assert_eq!(format!("{v2_psbt:00}"), "cHNidP8BAAoCAAAAAAAAAAAAAfsEAAAAAAA=");
1164        assert_eq!(format!("{v2_psbt:01}"), "cHNidP8BAAoCAAAAAAAAAAAAAfsEAAAAAAA=");
1165        assert_eq!(format!("{v0_psbt:02}"), "cHNidP8BAgQCAAAAAQQBAAEFAQAB+wQCAAAAAA==");
1166
1167        assert_eq!(format!("{v2_psbt:0}"), "cHNidP8BAAoCAAAAAAAAAAAAAfsEAAAAAAA=");
1168        assert_eq!(format!("{v2_psbt:1}"), "cHNidP8BAAoCAAAAAAAAAAAAAfsEAAAAAAA=");
1169        assert_eq!(format!("{v0_psbt:2}"), "cHNidP8BAgQCAAAAAQQBAAEFAQAB+wQCAAAAAA==");
1170
1171        assert_eq!(format!("{v2_psbt:#0}"), "cHNidP8BAAoCAAAAAAAAAAAAAfsEAAAAAAA=");
1172        assert_eq!(format!("{v2_psbt:#1}"), "cHNidP8BAAoCAAAAAAAAAAAAAfsEAAAAAAA=");
1173        assert_eq!(format!("{v0_psbt:#2}"), "cHNidP8BAgQCAAAAAQQBAAEFAQAB+wQCAAAAAA==");
1174
1175        // error formats
1176        let result = std::panic::catch_unwind(|| format!("{v0_psbt:03}"));
1177        assert!(result.is_err(), "Should fail on unsupported psbt version");
1178
1179        let result = std::panic::catch_unwind(|| format!("{v0_psbt:3}"));
1180        assert!(result.is_err(), "Should fail on unsupported psbt version");
1181
1182        let result = std::panic::catch_unwind(|| format!("{v0_psbt:#03}"));
1183        assert!(result.is_err(), "Should fail on unsupported psbt version");
1184
1185        let result = std::panic::catch_unwind(|| format!("{v0_psbt:#3}"));
1186        assert!(result.is_err(), "Should fail on unsupported psbt version");
1187
1188        let result = std::panic::catch_unwind(|| format!("{v0_psbt:#3x}"));
1189        assert!(result.is_err(), "Should fail on unsupported psbt version");
1190
1191        let result = std::panic::catch_unwind(|| format!("{v0_psbt:#03x}"));
1192        assert!(result.is_err(), "Should fail on unsupported psbt version");
1193    }
1194}