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