rustywallet_psbt/
output.rs

1//! PSBT output map
2
3use std::collections::BTreeMap;
4use crate::types::{KeySource, ProprietaryFields, UnknownFields};
5
6/// PSBT output map
7#[derive(Debug, Clone, Default)]
8pub struct OutputMap {
9    /// Redeem script (for P2SH outputs)
10    pub redeem_script: Option<Vec<u8>>,
11    /// Witness script (for P2WSH outputs)
12    pub witness_script: Option<Vec<u8>>,
13    /// BIP32 derivation paths (pubkey -> key source)
14    pub bip32_derivation: BTreeMap<Vec<u8>, KeySource>,
15    /// Taproot internal key
16    pub tap_internal_key: Option<Vec<u8>>,
17    /// Taproot tree
18    pub tap_tree: Option<Vec<u8>>,
19    /// Taproot BIP32 derivation
20    pub tap_bip32_derivation: BTreeMap<Vec<u8>, Vec<u8>>,
21    /// PSBT v2: Output amount
22    pub amount: Option<u64>,
23    /// PSBT v2: Output script
24    pub script: Option<Vec<u8>>,
25    /// Proprietary fields
26    pub proprietary: ProprietaryFields,
27    /// Unknown fields
28    pub unknown: UnknownFields,
29}
30
31impl OutputMap {
32    /// Create a new empty output map
33    pub fn new() -> Self {
34        Self::default()
35    }
36
37    /// Check if this is a change output (has BIP32 derivation info)
38    pub fn is_change(&self) -> bool {
39        !self.bip32_derivation.is_empty() || !self.tap_bip32_derivation.is_empty()
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn test_output_map_default() {
49        let output = OutputMap::new();
50        assert!(output.redeem_script.is_none());
51        assert!(output.witness_script.is_none());
52        assert!(output.bip32_derivation.is_empty());
53        assert!(!output.is_change());
54    }
55
56    #[test]
57    fn test_output_is_change() {
58        let mut output = OutputMap::new();
59        assert!(!output.is_change());
60
61        output.bip32_derivation.insert(
62            vec![0x02; 33],
63            KeySource::new([0x01, 0x02, 0x03, 0x04], vec![84 | 0x80000000, 0x80000000, 0x80000000, 1, 0]),
64        );
65        assert!(output.is_change());
66    }
67}