@@ -19,7 +19,9 @@ use crate::TxOrdering;
1919#[ derive( Debug ) ]
2020pub struct PsbtParams {
2121 // Inputs
22- pub ( crate ) utxos : SelectedOutpoints ,
22+ pub ( crate ) set : HashSet < OutPoint > ,
23+ pub ( crate ) utxos : Vec < OutPoint > ,
24+ pub ( crate ) inputs : Vec < Input > ,
2325
2426 // Outputs
2527 pub ( crate ) recipients : Vec < ( ScriptBuf , Amount ) > ,
@@ -44,7 +46,9 @@ pub struct PsbtParams {
4446impl Default for PsbtParams {
4547 fn default ( ) -> Self {
4648 Self {
49+ set : Default :: default ( ) ,
4750 utxos : Default :: default ( ) ,
51+ inputs : Default :: default ( ) ,
4852 assets : Default :: default ( ) ,
4953 recipients : Default :: default ( ) ,
5054 change_descriptor : Default :: default ( ) ,
@@ -69,18 +73,21 @@ impl PsbtParams {
6973 /// responsible for ensuring that elements of `outpoints` correspond to outputs of previous
7074 /// transactions and are currently unspent.
7175 pub fn add_utxos ( & mut self , outpoints : & [ OutPoint ] ) -> & mut Self {
72- self . utxos . extend ( outpoints. iter ( ) . copied ( ) ) ;
76+ self . utxos
77+ . extend ( outpoints. iter ( ) . copied ( ) . filter ( |& op| self . set . insert ( op) ) ) ;
7378 self
7479 }
7580
7681 /// Get the currently selected spends.
77- pub fn utxos ( & self ) -> & Vec < OutPoint > {
78- self . utxos . utxos ( )
82+ pub fn utxos ( & self ) -> & HashSet < OutPoint > {
83+ & self . set
7984 }
8085
8186 /// Remove a UTXO from the currently selected inputs.
8287 pub fn remove_utxo ( & mut self , outpoint : & OutPoint ) -> & mut Self {
83- self . utxos . remove ( outpoint) ;
88+ if self . set . remove ( outpoint) {
89+ self . utxos . retain ( |op| op != outpoint) ;
90+ }
8491 self
8592 }
8693
@@ -185,41 +192,18 @@ impl PsbtParams {
185192 self . ordering = ordering;
186193 self
187194 }
188- }
189-
190- /// Structure containing the set of outpoints that are manually selected. This
191- /// ensures that no single outpoint appears more than once in the inputs, while preserving
192- /// the order in which they are added to the [`PsbtParams`].
193- #[ derive( Debug , Clone , Default ) ]
194- pub ( crate ) struct SelectedOutpoints {
195- /// Unique set of selected outpoints.
196- set : HashSet < OutPoint > ,
197- /// UTXOs added.
198- pub utxos : Vec < OutPoint > ,
199- }
200-
201- impl SelectedOutpoints {
202- /// Add an outpoint.
203- fn extend ( & mut self , outpoints : impl IntoIterator < Item = OutPoint > ) {
204- self . utxos
205- . extend ( outpoints. into_iter ( ) . filter ( |& op| self . set . insert ( op) ) )
206- }
207195
208- /// Remove an outpoint.
209- fn remove ( & mut self , outpoint : & OutPoint ) {
210- if self . set . remove ( outpoint) {
211- self . utxos . retain ( |op| op != outpoint)
196+ /// Add a planned input.
197+ ///
198+ /// This can be used to add inputs that come with a [`Plan`] or [`psbt::Input`] provided.
199+ ///
200+ /// [`Plan`]: miniscript::plan::Plan
201+ /// [`psbt::Input`]: bitcoin::psbt::Input
202+ pub fn add_planned_input ( & mut self , input : Input ) -> & mut Self {
203+ if self . set . insert ( input. prev_outpoint ( ) ) {
204+ self . inputs . push ( input) ;
212205 }
213- }
214-
215- /// Whether the current selection contains the given `outpoint`.
216- pub fn contains ( & self , outpoint : & OutPoint ) -> bool {
217- self . set . contains ( outpoint)
218- }
219-
220- /// Get the selected spends (UTXOs).
221- fn utxos ( & self ) -> & Vec < OutPoint > {
222- & self . utxos
206+ self
223207 }
224208}
225209
@@ -262,26 +246,27 @@ pub struct ReplaceParams {
262246}
263247
264248impl ReplaceParams {
265- /// Construct from PSBT `params` and an iterator of `txs` to replace.
266- pub ( crate ) fn new ( txs : & [ Arc < Transaction > ] , params : PsbtParams ) -> Self {
267- Self {
268- inner : params ,
249+ /// Construct from `inner` params and the `txs` to replace.
250+ pub ( crate ) fn new ( txs : & [ Arc < Transaction > ] , inner : PsbtParams ) -> Self {
251+ let mut params = Self {
252+ inner,
269253 ..Default :: default ( )
270- }
271- . replace ( txs)
254+ } ;
255+ params. replace ( txs) ;
256+ params
272257 }
273258
274259 /// Replace spends of the provided `txs`. This will internally set the internal list
275260 /// of UTXOs to be spent.
276- pub fn replace ( self , txs : & [ Arc < Transaction > ] ) -> Self {
277- let txs : Vec < Arc < Transaction > > = txs . to_vec ( ) ;
278- let mut txids : HashSet < Txid > = txs . iter ( ) . map ( |tx| tx . compute_txid ( ) ) . collect ( ) ;
279- let mut tx_graph = TxGraph :: < BlockId > :: default ( ) ;
280- let mut utxos = SelectedOutpoints :: default ( ) ;
281-
282- for tx in txs {
283- let _ = tx_graph . insert_tx ( tx ) ;
284- }
261+ pub fn replace ( & mut self , txs : & [ Arc < Transaction > ] ) {
262+ self . inner . utxos . clear ( ) ;
263+ let mut utxos = vec ! [ ] ;
264+
265+ let ( mut txids_to_replace , txs ) : ( HashSet < Txid > , Vec < Transaction > ) = txs
266+ . iter ( )
267+ . map ( |tx| ( tx . compute_txid ( ) , tx . as_ref ( ) . clone ( ) ) )
268+ . unzip ( ) ;
269+ let tx_graph = TxGraph :: < BlockId > :: new ( txs ) ;
285270
286271 // Sanitize the RBF set by removing elements of `txs` which have ancestors
287272 // in the same set. This is to avoid spending outputs of txs that are bound
@@ -291,21 +276,16 @@ impl ReplaceParams {
291276 if tx. is_coinbase ( )
292277 || tx_graph
293278 . walk_ancestors ( Arc :: clone ( tx) , |_, tx| Some ( tx. compute_txid ( ) ) )
294- . any ( |ancestor_txid| txids . contains ( & ancestor_txid) )
279+ . any ( |ancestor_txid| txids_to_replace . contains ( & ancestor_txid) )
295280 {
296- txids . remove ( & tx_node. txid ) ;
281+ txids_to_replace . remove ( & tx_node. txid ) ;
297282 } else {
298283 utxos. extend ( tx. input . iter ( ) . map ( |txin| txin. previous_output ) ) ;
299284 }
300285 }
301286
302- Self {
303- inner : PsbtParams {
304- utxos,
305- ..self . inner
306- } ,
307- replace : txids,
308- }
287+ self . replace = txids_to_replace;
288+ self . inner . add_utxos ( & utxos) ;
309289 }
310290
311291 /// Add recipients.
@@ -325,8 +305,8 @@ impl ReplaceParams {
325305 }
326306
327307 /// Get the currently selected spends.
328- pub fn utxos ( & self ) -> & Vec < OutPoint > {
329- self . inner . utxos ( )
308+ pub fn utxos ( & self ) -> & HashSet < OutPoint > {
309+ & self . inner . set
330310 }
331311
332312 /// Remove a UTXO from the currently selected inputs.
@@ -416,7 +396,7 @@ mod test {
416396 let txs: Vec < Arc < Transaction > > =
417397 [ tx_a, tx_b, tx_c, tx_d] . into_iter ( ) . map ( Arc :: new) . collect ( ) ;
418398 let params = ReplaceParams :: new ( & txs, PsbtParams :: default ( ) ) ;
419- assert_eq ! ( params. inner. utxos . set, expect_spends) ;
399+ assert_eq ! ( params. inner. set, expect_spends) ;
420400 assert_eq ! ( params. replace, [ txid_a, txid_c] . into( ) ) ;
421401 }
422402
@@ -431,20 +411,20 @@ mod test {
431411 }
432412 assert_eq ! (
433413 params. utxos( ) ,
434- & vec! [ op] ,
414+ & [ op] . into ( ) ,
435415 "Failed to filter duplicate outpoints"
436416 ) ;
437- assert ! ( params. utxos . contains ( & op ) ) ;
417+ assert_eq ! ( params. set , [ op ] . into ( ) ) ;
438418
439- params. utxos = SelectedOutpoints :: default ( ) ;
419+ params. utxos = vec ! [ ] ;
440420
441421 // Try adding duplicates in the same set.
442422 params. add_utxos ( & [ op, op, op] ) ;
443423 assert_eq ! (
444424 params. utxos( ) ,
445- & vec! [ op] ,
425+ & [ op] . into ( ) ,
446426 "Failed to filter duplicate outpoints"
447427 ) ;
448- assert ! ( params. utxos . contains ( & op ) ) ;
428+ assert_eq ! ( params. set , [ op ] . into ( ) ) ;
449429 }
450430}
0 commit comments