@@ -10,7 +10,9 @@ use bdk_chain::{
1010use bitcoin:: {
1111 absolute, hashes:: Hash , BlockHash , OutPoint , ScriptBuf , Transaction , TxIn , TxOut , Txid ,
1212} ;
13+ use common:: * ;
1314use core:: iter;
15+ use rand:: RngCore ;
1416use std:: vec;
1517
1618#[ test]
@@ -1172,3 +1174,86 @@ fn test_missing_blocks() {
11721174 ) ,
11731175 ] ) ;
11741176}
1177+
1178+ #[ test]
1179+ /// The `map_anchors` allow a caller to pass a function to reconstruct the [`TxGraph`] with any [`Anchor`],
1180+ /// even though the function is non-deterministic.
1181+ fn call_map_anchors_with_non_deterministic_anchor ( ) {
1182+ #[ derive( Debug , Default , Clone , PartialEq , Eq , Copy , PartialOrd , Ord , core:: hash:: Hash ) ]
1183+ /// A non-deterministic anchor
1184+ pub struct NonDeterministicAnchor {
1185+ pub anchor_block : BlockId ,
1186+ pub non_deterministic_field : u32 ,
1187+ }
1188+
1189+ let template = [
1190+ TxTemplate {
1191+ tx_name : "tx1" ,
1192+ inputs : & [ TxInTemplate :: Bogus ] ,
1193+ outputs : & [ TxOutTemplate :: new ( 10000 , Some ( 1 ) ) ] ,
1194+ anchors : & [ block_id ! ( 1 , "A" ) ] ,
1195+ last_seen : None ,
1196+ } ,
1197+ TxTemplate {
1198+ tx_name : "tx2" ,
1199+ inputs : & [ TxInTemplate :: PrevTx ( "tx1" , 0 ) ] ,
1200+ outputs : & [ TxOutTemplate :: new ( 20000 , Some ( 2 ) ) ] ,
1201+ anchors : & [ block_id ! ( 2 , "B" ) ] ,
1202+ ..Default :: default ( )
1203+ } ,
1204+ TxTemplate {
1205+ tx_name : "tx3" ,
1206+ inputs : & [ TxInTemplate :: PrevTx ( "tx2" , 0 ) ] ,
1207+ outputs : & [ TxOutTemplate :: new ( 30000 , Some ( 3 ) ) ] ,
1208+ anchors : & [ block_id ! ( 3 , "C" ) , block_id ! ( 4 , "D" ) ] ,
1209+ ..Default :: default ( )
1210+ } ,
1211+ ] ;
1212+ let ( graph, _, _) = init_graph ( & template) ;
1213+ let new_graph = graph. clone ( ) . map_anchors ( |a| NonDeterministicAnchor {
1214+ anchor_block : a,
1215+ // A non-deterministic value
1216+ non_deterministic_field : rand:: thread_rng ( ) . next_u32 ( ) ,
1217+ } ) ;
1218+
1219+ // Check all the details in new_graph reconstruct as well
1220+
1221+ let mut full_txs_vec: Vec < _ > = graph. full_txs ( ) . collect ( ) ;
1222+ full_txs_vec. sort ( ) ;
1223+ let mut new_txs_vec: Vec < _ > = new_graph. full_txs ( ) . collect ( ) ;
1224+ new_txs_vec. sort ( ) ;
1225+ let mut new_txs = new_txs_vec. iter ( ) ;
1226+
1227+ for tx_node in full_txs_vec. iter ( ) {
1228+ let new_txnode = new_txs. next ( ) . unwrap ( ) ;
1229+ assert_eq ! ( new_txnode. txid, tx_node. txid) ;
1230+ assert_eq ! ( new_txnode. tx, tx_node. tx) ;
1231+ assert_eq ! (
1232+ new_txnode. last_seen_unconfirmed,
1233+ tx_node. last_seen_unconfirmed
1234+ ) ;
1235+ assert_eq ! ( new_txnode. anchors. len( ) , tx_node. anchors. len( ) ) ;
1236+
1237+ let mut new_anchors: Vec < _ > = new_txnode. anchors . iter ( ) . map ( |a| a. anchor_block ) . collect ( ) ;
1238+ new_anchors. sort ( ) ;
1239+ let mut old_anchors: Vec < _ > = tx_node. anchors . iter ( ) . copied ( ) . collect ( ) ;
1240+ old_anchors. sort ( ) ;
1241+ assert_eq ! ( new_anchors, old_anchors) ;
1242+ }
1243+ assert ! ( new_txs. next( ) . is_none( ) ) ;
1244+
1245+ let new_graph_anchors: Vec < _ > = new_graph
1246+ . all_anchors ( )
1247+ . iter ( )
1248+ . map ( |i| i. 0 . anchor_block )
1249+ . collect ( ) ;
1250+ assert_eq ! (
1251+ new_graph_anchors,
1252+ vec![
1253+ block_id!( 1 , "A" ) ,
1254+ block_id!( 2 , "B" ) ,
1255+ block_id!( 3 , "C" ) ,
1256+ block_id!( 4 , "D" ) ,
1257+ ]
1258+ ) ;
1259+ }
0 commit comments