rustywallet_psbt/
lib.rs

1//! # rustywallet-psbt
2//!
3//! PSBT (Partially Signed Bitcoin Transaction) implementation for Bitcoin wallet development.
4//!
5//! This crate implements BIP174 (PSBT v0) and BIP370 (PSBT v2) for hardware wallet
6//! interoperability and multi-party signing workflows.
7//!
8//! ## Features
9//!
10//! - Parse and create PSBTs
11//! - Sign PSBTs with private keys
12//! - Combine PSBTs from multiple signers
13//! - Finalize PSBTs and extract signed transactions
14//! - Support for P2PKH, P2WPKH, P2SH, P2WSH, and P2TR inputs
15//! - PSBT v2 (BIP370) support
16//!
17//! ## Example
18//!
19//! ```rust,no_run
20//! use rustywallet_psbt::{Psbt, PsbtError};
21//!
22//! // Parse PSBT from base64
23//! let psbt_base64 = "cHNidP8BAH...";
24//! let mut psbt = Psbt::from_base64(psbt_base64)?;
25//!
26//! // Sign with private key
27//! // let signed = psbt.sign(&private_key)?;
28//!
29//! // Finalize
30//! psbt.finalize()?;
31//!
32//! // Extract signed transaction
33//! let tx = psbt.extract_tx()?;
34//! # Ok::<(), PsbtError>(())
35//! ```
36//!
37//! ## BIP174 Roles
38//!
39//! This crate implements all BIP174 roles:
40//!
41//! - **Creator**: Create PSBT from unsigned transaction
42//! - **Updater**: Add UTXO info, scripts, derivation paths
43//! - **Signer**: Add partial signatures
44//! - **Combiner**: Merge PSBTs from multiple signers
45//! - **Finalizer**: Construct final scriptSig/witness
46//! - **Extractor**: Extract signed transaction
47
48pub mod error;
49pub mod global;
50pub mod input;
51pub mod output;
52pub mod psbt;
53pub mod serialize;
54pub mod types;
55
56mod combiner;
57mod finalizer;
58mod signer;
59
60// Re-exports
61pub use error::PsbtError;
62pub use global::GlobalMap;
63pub use input::{InputMap, TxOut, Witness};
64pub use output::OutputMap;
65pub use psbt::Psbt;
66pub use types::{KeySource, PsbtSighashType};
67
68/// Prelude module for convenient imports
69pub mod prelude {
70    pub use crate::error::PsbtError;
71    pub use crate::global::GlobalMap;
72    pub use crate::input::{InputMap, TxOut, Witness};
73    pub use crate::output::OutputMap;
74    pub use crate::psbt::Psbt;
75    pub use crate::types::{KeySource, PsbtSighashType};
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    fn test_psbt_magic() {
84        let magic = types::PSBT_MAGIC;
85        assert_eq!(magic, [0x70, 0x73, 0x62, 0x74, 0xff]);
86        assert_eq!(&magic[0..4], b"psbt");
87    }
88
89    #[test]
90    fn test_create_psbt() {
91        // Minimal unsigned transaction
92        let tx = vec![
93            0x02, 0x00, 0x00, 0x00, // version
94            0x00, // no inputs
95            0x00, // no outputs
96            0x00, 0x00, 0x00, 0x00, // locktime
97        ];
98
99        let psbt = Psbt::from_unsigned_tx(tx).unwrap();
100        assert_eq!(psbt.version(), 0);
101        assert_eq!(psbt.input_count(), 0);
102        assert_eq!(psbt.output_count(), 0);
103    }
104
105    #[test]
106    fn test_psbt_serialization() {
107        let tx = vec![
108            0x02, 0x00, 0x00, 0x00, // version
109            0x00, // no inputs
110            0x00, // no outputs
111            0x00, 0x00, 0x00, 0x00, // locktime
112        ];
113
114        let psbt = Psbt::from_unsigned_tx(tx).unwrap();
115        let bytes = psbt.to_bytes();
116
117        // Check magic
118        assert_eq!(&bytes[0..5], &types::PSBT_MAGIC);
119
120        // Roundtrip
121        let parsed = Psbt::from_bytes(&bytes).unwrap();
122        assert_eq!(psbt.to_bytes(), parsed.to_bytes());
123    }
124}