@@ -72,15 +72,7 @@ impl LipaChainAccess {
7272 debug ! ( "{} confirmed transactions" , confirmed_txs. len( ) ) ;
7373 debug ! ( "Confirmed transaction list: {:?}" , confirmed_txs) ;
7474
75- // Sort all confirmed transactions by block height and feed them to the interface
76- // in order.
77- confirmed_txs. sort_unstable_by ( |( _, block_height1, _, _) , ( _, block_height2, _, _) | {
78- block_height1. cmp ( block_height2)
79- } ) ;
80-
81- // todo also sort within block
82- // From the Confirm trait documentation:
83- // Dependent transactions within the same block must be given in topological order, possibly in separate calls
75+ sort_txs ( & mut confirmed_txs) ;
8476
8577 for ( tx, block_height, block_header, pos) in confirmed_txs {
8678 for c in & confirmables {
@@ -368,6 +360,16 @@ impl LipaChainAccess {
368360 }
369361}
370362
363+ // Sorting by blocks and by transaction position within the each block
364+ // From the Confirm trait documentation:
365+ // - Transactions confirmed in a block must be given before transactions confirmed in a later
366+ // block.
367+ // - Dependent transactions within the same block must be given in topological order, possibly in
368+ // separate calls.
369+ fn sort_txs ( txs : & mut [ ( Transaction , u32 , BlockHeader , usize ) ] ) {
370+ txs. sort_unstable_by_key ( |tx| ( tx. 1 , tx. 3 ) ) ;
371+ }
372+
371373impl Filter for LipaChainAccess {
372374 fn register_tx ( & self , txid : & Txid , script_pubkey : & Script ) {
373375 self . queued_txs
@@ -388,10 +390,11 @@ impl Filter for LipaChainAccess {
388390
389391#[ cfg( test) ]
390392mod tests {
393+ use crate :: chain_access:: sort_txs;
391394 use crate :: LipaChainAccess ;
392395 use bitcoin:: consensus:: deserialize;
393396 use bitcoin:: hashes:: hex:: FromHex ;
394- use bitcoin:: Transaction ;
397+ use bitcoin:: { BlockHeader , Transaction } ;
395398 use esplora_client:: Builder ;
396399 use lightning:: chain:: transaction:: OutPoint ;
397400 use lightning:: chain:: { Filter , WatchedOutput } ;
@@ -417,6 +420,17 @@ mod tests {
417420 tx. unwrap ( )
418421 }
419422
423+ fn build_default_block_header ( ) -> BlockHeader {
424+ BlockHeader {
425+ version : 0 ,
426+ prev_blockhash : Default :: default ( ) ,
427+ merkle_root : Default :: default ( ) ,
428+ time : 0 ,
429+ bits : 0 ,
430+ nonce : 0 ,
431+ }
432+ }
433+
420434 #[ test]
421435 fn filter_is_initialised_empty ( ) {
422436 let filter = build_filter ( ) ;
@@ -480,4 +494,49 @@ mod tests {
480494 assert_eq ! ( filter_output. outpoint, output. outpoint) ;
481495 assert_eq ! ( filter_output. block_hash, output. block_hash) ;
482496 }
497+
498+ #[ test]
499+ fn txs_are_sorted_by_block_and_position_within_block ( ) {
500+ let mut txs = vec ! [
501+ (
502+ build_sample_tx( ) ,
503+ 10 , // block height
504+ build_default_block_header( ) ,
505+ 10 , // position within block
506+ ) ,
507+ (
508+ build_sample_tx( ) ,
509+ 5 , // block height
510+ build_default_block_header( ) ,
511+ 5 , // position within block
512+ ) ,
513+ (
514+ build_sample_tx( ) ,
515+ 10 , // block height
516+ build_default_block_header( ) ,
517+ 5 , // position within block
518+ ) ,
519+ (
520+ build_sample_tx( ) ,
521+ 5 , // block height
522+ build_default_block_header( ) ,
523+ 10 , // position within block
524+ ) ,
525+ ] ;
526+
527+ let unsorted: Vec < ( u32 , usize ) > = txs
528+ . iter ( )
529+ . map ( |( _, block_height, _, pos_within_block) | ( * block_height, * pos_within_block) )
530+ . collect ( ) ;
531+
532+ sort_txs ( & mut txs) ;
533+
534+ let sorted: Vec < ( u32 , usize ) > = txs
535+ . iter ( )
536+ . map ( |( _, block_height, _, pos_within_block) | ( * block_height, * pos_within_block) )
537+ . collect ( ) ;
538+
539+ assert_eq ! ( unsorted, vec![ ( 10 , 10 ) , ( 5 , 5 ) , ( 10 , 5 ) , ( 5 , 10 ) ] ) ;
540+ assert_eq ! ( sorted, vec![ ( 5 , 5 ) , ( 5 , 10 ) , ( 10 , 5 ) , ( 10 , 10 ) ] ) ;
541+ }
483542}
0 commit comments