1+ //! Script pubkey types and operations.
2+ //!
3+ //! This module provides types for working with script pubkeys (also known as
4+ //! "locking scripts"), which define the conditions that must be met to spend a
5+ //! [`TxOut`].
6+ //!
7+ //! # Types
8+ //!
9+ //! The module provides two types:
10+ //!
11+ //! - [`ScriptPubkey`]: An owned script pubkey that manages its own memory
12+ //! - [`ScriptPubkeyRef`]: A borrowed reference to a script pubkey with a specific lifetime
13+ //!
14+ //! Both types implement the [`ScriptPubkeyExt`] trait, providing a unified interface
15+ //! for all script pubkey operations regardless of ownership.
16+ //!
17+ //! # Examples
18+ //!
19+ //! ## Creating and working with script pubkeys
20+ //!
21+ //! ```no_run
22+ //! # use bitcoinkernel::{prelude::*, ScriptPubkey};
23+ //! // Create a simple script from raw bytes
24+ //! let script = ScriptPubkey::new(&[0x76, 0xa9, 0x14]).unwrap();
25+ //!
26+ //! // Serialize back to bytes
27+ //! let bytes = script.to_bytes();
28+ //! assert_eq!(bytes, vec![0x76, 0xa9, 0x14]);
29+ //!
30+ //! // Use TryFrom for conversion
31+ //! let script2 = ScriptPubkey::try_from(bytes.as_slice()).unwrap();
32+ //! ```
33+ //!
34+ //! ## Creating standard script types
35+ //!
36+ //! ```no_run
37+ //! # use bitcoinkernel::ScriptPubkey;
38+ //! // P2PKH: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
39+ //! let p2pkh_hex = "76a914deadbeefdeadbeefdeadbeefdeadbeefdeadbeef88ac";
40+ //! let p2pkh = ScriptPubkey::new(&hex::decode(p2pkh_hex).unwrap()).unwrap();
41+ //!
42+ //! // P2SH: OP_HASH160 <scriptHash> OP_EQUAL
43+ //! let p2sh_hex = "a914deadbeefdeadbeefdeadbeefdeadbeefdeadbeef87";
44+ //! let p2sh = ScriptPubkey::new(&hex::decode(p2sh_hex).unwrap()).unwrap();
45+ //!
46+ //! // P2WPKH: OP_0 <20-byte-pubkey-hash>
47+ //! let p2wpkh_hex = "0014deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
48+ //! let p2wpkh = ScriptPubkey::new(&hex::decode(p2wpkh_hex).unwrap()).unwrap();
49+ //! ```
50+
151use std:: { ffi:: c_void, marker:: PhantomData } ;
252
353use libbitcoinkernel_sys:: {
@@ -12,8 +62,22 @@ use crate::{
1262} ;
1363
1464/// Common operations for script pubkeys, implemented by both owned and borrowed types.
65+ ///
66+ /// This trait provides shared functionality for [`ScriptPubkey`] and [`ScriptPubkeyRef`],
67+ /// allowing code to work with either owned or borrowed script pubkeys.
1568pub trait ScriptPubkeyExt : AsPtr < btck_ScriptPubkey > {
1669 /// Serializes the script to raw bytes.
70+ ///
71+ /// Returns the script's raw byte representation.
72+ ///
73+ /// # Examples
74+ ///
75+ /// ```no_run
76+ /// # use bitcoinkernel::{prelude::*, ScriptPubkey};
77+ /// let script = ScriptPubkey::new(&[0x76, 0xa9]).unwrap();
78+ /// let bytes = script.to_bytes();
79+ /// assert_eq!(bytes, vec![0x76, 0xa9]);
80+ /// ```
1781 fn to_bytes ( & self ) -> Vec < u8 > {
1882 c_serialize ( |callback, user_data| unsafe {
1983 btck_script_pubkey_to_bytes ( self . as_ptr ( ) , Some ( callback) , user_data)
@@ -22,10 +86,25 @@ pub trait ScriptPubkeyExt: AsPtr<btck_ScriptPubkey> {
2286 }
2387}
2488
25- /// A single script pubkey containing spending conditions for a transaction output.
89+ /// A single script pubkey containing spending conditions for a [`TxOut`].
90+ ///
91+ /// Script pubkeys define the conditions that must be met to spend a transaction output.
92+ /// They are also called "locking scripts" because they lock the output to specific
93+ /// spending conditions.
94+ ///
95+ /// Script pubkeys can be created from raw script bytes or retrieved from an existing
96+ /// [`TxOut`].
97+ ///
98+ /// # Examples
2699///
27- /// Script pubkeys can be created from raw script bytes or retrieved from existing
28- /// transaction outputs.
100+ /// Creating a simple script:
101+ ///
102+ /// ```no_run
103+ /// # use bitcoinkernel::{prelude::*, ScriptPubkey};
104+ /// let script_bytes = vec![0x76, 0xa9, 0x14]; // OP_DUP OP_HASH160 OP_PUSHBYTES_20
105+ /// let script = ScriptPubkey::new(&script_bytes).unwrap();
106+ /// assert_eq!(script.to_bytes(), script_bytes);
107+ /// ```
29108#[ derive( Debug ) ]
30109pub struct ScriptPubkey {
31110 inner : * mut btck_ScriptPubkey ,
@@ -35,6 +114,28 @@ unsafe impl Send for ScriptPubkey {}
35114unsafe impl Sync for ScriptPubkey { }
36115
37116impl ScriptPubkey {
117+ /// Creates a new script pubkey from raw script bytes.
118+ ///
119+ /// # Arguments
120+ ///
121+ /// * `script_bytes` - The raw bytes representing the script
122+ ///
123+ /// # Returns
124+ ///
125+ /// * `Ok(ScriptPubkey)` - Successfully created script pubkey
126+ /// * `Err(KernelError::Internal)` - If the script could not be created
127+ ///
128+ /// # Examples
129+ ///
130+ /// ```no_run
131+ /// # use bitcoinkernel::ScriptPubkey;
132+ /// // Create a P2PKH script
133+ /// let p2pkh = ScriptPubkey::new(&[
134+ /// 0x76, 0xa9, 0x14, // OP_DUP OP_HASH160 OP_PUSHBYTES_20
135+ /// // ... pubkey hash bytes ...
136+ /// 0x88, 0xac // OP_EQUALVERIFY OP_CHECKSIG
137+ /// ]).unwrap();
138+ /// ```
38139 pub fn new ( script_bytes : & [ u8 ] ) -> Result < Self , KernelError > {
39140 let inner = unsafe {
40141 btck_script_pubkey_create ( script_bytes. as_ptr ( ) as * const c_void , script_bytes. len ( ) )
@@ -49,6 +150,13 @@ impl ScriptPubkey {
49150 }
50151 }
51152
153+ /// Creates a borrowed reference to this script pubkey.
154+ ///
155+ /// This allows converting from an owned [`ScriptPubkey`] to a [`ScriptPubkeyRef`]
156+ /// without copying the underlying data.
157+ ///
158+ /// # Lifetime
159+ /// The returned reference is valid for the lifetime of this [`ScriptPubkey`].
52160 pub fn as_ref ( & self ) -> ScriptPubkeyRef < ' _ > {
53161 unsafe { ScriptPubkeyRef :: from_ptr ( self . inner as * const _ ) }
54162 }
@@ -102,6 +210,16 @@ impl From<&ScriptPubkey> for Vec<u8> {
102210 }
103211}
104212
213+ /// A borrowed reference to a script pubkey.
214+ ///
215+ /// Provides zero-copy access to script pubkey data. It implements [`Copy`],
216+ /// making it cheap to pass around.
217+ ///
218+ /// # Lifetime
219+ /// The reference is only valid as long as the data it references remains alive.
220+ ///
221+ /// # Thread Safety
222+ /// `ScriptPubkeyRef` is both [`Send`] and [`Sync`].
105223pub struct ScriptPubkeyRef < ' a > {
106224 inner : * const btck_ScriptPubkey ,
107225 marker : PhantomData < & ' a ( ) > ,
@@ -111,6 +229,21 @@ unsafe impl<'a> Send for ScriptPubkeyRef<'a> {}
111229unsafe impl < ' a > Sync for ScriptPubkeyRef < ' a > { }
112230
113231impl < ' a > ScriptPubkeyRef < ' a > {
232+ /// Creates an owned copy of this script pubkey.
233+ ///
234+ /// This allocates a new [`ScriptPubkey`] with its own copy of the script data.
235+ ///
236+ /// # Examples
237+ ///
238+ /// ```no_run
239+ /// # use bitcoinkernel::{prelude::*, ScriptPubkey};
240+ /// let owned_script = {
241+ /// let script = ScriptPubkey::new(&[0x76, 0xa9]).unwrap();
242+ /// let script_ref = script.as_ref();
243+ /// script_ref.to_owned() // Survives after script is dropped
244+ /// };
245+ /// assert_eq!(owned_script.to_bytes(), vec![0x76, 0xa9]);
246+ /// ```
114247 pub fn to_owned ( & self ) -> ScriptPubkey {
115248 ScriptPubkey {
116249 inner : unsafe { btck_script_pubkey_copy ( self . inner ) } ,
0 commit comments