@@ -10,6 +10,8 @@ use bdk_chain::{
10
10
Anchor , ChainOracle , ChainPosition , Merge ,
11
11
} ;
12
12
use bdk_testenv:: { block_id, hash, utils:: new_tx} ;
13
+ use bitcoin:: hex:: FromHex ;
14
+ use bitcoin:: Witness ;
13
15
use bitcoin:: {
14
16
absolute, hashes:: Hash , transaction, Amount , BlockHash , OutPoint , ScriptBuf , SignedAmount ,
15
17
Transaction , TxIn , TxOut , Txid ,
@@ -282,6 +284,74 @@ fn insert_tx_displaces_txouts() {
282
284
assert_eq ! ( tx_graph. get_txout( outpoint) , Some ( txout) ) ;
283
285
}
284
286
287
+ #[ test]
288
+ fn insert_signed_tx_displaces_unsigned ( ) {
289
+ let previous_output = OutPoint :: new ( hash ! ( "prev" ) , 2 ) ;
290
+ let unsigned_tx = Transaction {
291
+ version : transaction:: Version :: ONE ,
292
+ lock_time : absolute:: LockTime :: ZERO ,
293
+ input : vec ! [ TxIn {
294
+ previous_output,
295
+ script_sig: ScriptBuf :: default ( ) ,
296
+ sequence: transaction:: Sequence :: ENABLE_RBF_NO_LOCKTIME ,
297
+ witness: Witness :: default ( ) ,
298
+ } ] ,
299
+ output : vec ! [ TxOut {
300
+ value: Amount :: from_sat( 24_000 ) ,
301
+ script_pubkey: ScriptBuf :: default ( ) ,
302
+ } ] ,
303
+ } ;
304
+ let signed_tx = Transaction {
305
+ input : vec ! [ TxIn {
306
+ previous_output,
307
+ script_sig: ScriptBuf :: default ( ) ,
308
+ sequence: transaction:: Sequence :: ENABLE_RBF_NO_LOCKTIME ,
309
+ witness: Witness :: from_slice( & [
310
+ // Random witness from mempool.space
311
+ Vec :: from_hex( "d59118058bf9e8604cec5c0b4a13430b07286482784da313594e932faad074dc4bd27db7cbfff9ad32450db097342d0148ec21c3033b0c27888fd2fd0de2e9b5" )
312
+ . unwrap( ) ,
313
+ ] ) ,
314
+ } ] ,
315
+ ..unsigned_tx. clone ( )
316
+ } ;
317
+
318
+ // Signed tx must displace unsigned.
319
+ {
320
+ let mut tx_graph = TxGraph :: < ConfirmationBlockTime > :: default ( ) ;
321
+ let changeset_insert_unsigned = tx_graph. insert_tx ( unsigned_tx. clone ( ) ) ;
322
+ let changeset_insert_signed = tx_graph. insert_tx ( signed_tx. clone ( ) ) ;
323
+ assert_eq ! (
324
+ changeset_insert_unsigned,
325
+ ChangeSet {
326
+ txs: [ Arc :: new( unsigned_tx. clone( ) ) ] . into( ) ,
327
+ ..Default :: default ( )
328
+ }
329
+ ) ;
330
+ assert_eq ! (
331
+ changeset_insert_signed,
332
+ ChangeSet {
333
+ txs: [ Arc :: new( signed_tx. clone( ) ) ] . into( ) ,
334
+ ..Default :: default ( )
335
+ }
336
+ ) ;
337
+ }
338
+
339
+ // Unsigned tx must not displace signed.
340
+ {
341
+ let mut tx_graph = TxGraph :: < ConfirmationBlockTime > :: default ( ) ;
342
+ let changeset_insert_signed = tx_graph. insert_tx ( signed_tx. clone ( ) ) ;
343
+ let changeset_insert_unsigned = tx_graph. insert_tx ( unsigned_tx. clone ( ) ) ;
344
+ assert_eq ! (
345
+ changeset_insert_signed,
346
+ ChangeSet {
347
+ txs: [ Arc :: new( signed_tx) ] . into( ) ,
348
+ ..Default :: default ( )
349
+ }
350
+ ) ;
351
+ assert ! ( changeset_insert_unsigned. is_empty( ) ) ;
352
+ }
353
+ }
354
+
285
355
#[ test]
286
356
fn insert_txout_does_not_displace_tx ( ) {
287
357
let mut tx_graph = TxGraph :: < ConfirmationBlockTime > :: default ( ) ;
0 commit comments