@@ -77,28 +77,60 @@ pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &T
7777}
7878
7979/// The possible ways we may notify a ChannelManager of a new block
80- #[ derive( Clone , Copy , PartialEq ) ]
80+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
8181pub enum ConnectStyle {
82- /// Calls best_block_updated first, detecting transactions in the block only after receiving the
83- /// header and height information.
82+ /// Calls ` best_block_updated` first, detecting transactions in the block only after receiving
83+ /// the header and height information.
8484 BestBlockFirst ,
85- /// The same as BestBlockFirst, however when we have multiple blocks to connect, we only
86- /// make a single best_block_updated call.
85+ /// The same as ` BestBlockFirst` , however when we have multiple blocks to connect, we only
86+ /// make a single ` best_block_updated` call.
8787 BestBlockFirstSkippingBlocks ,
88- /// Calls transactions_confirmed first, detecting transactions in the block before updating the
89- /// header and height information.
88+ /// The same as `BestBlockFirst` when connecting blocks. During disconnection only
89+ /// `transaction_unconfirmed` is called.
90+ BestBlockFirstReorgsOnlyTip ,
91+ /// Calls `transactions_confirmed` first, detecting transactions in the block before updating
92+ /// the header and height information.
9093 TransactionsFirst ,
91- /// The same as TransactionsFirst, however when we have multiple blocks to connect, we only
92- /// make a single best_block_updated call.
94+ /// The same as ` TransactionsFirst` , however when we have multiple blocks to connect, we only
95+ /// make a single ` best_block_updated` call.
9396 TransactionsFirstSkippingBlocks ,
94- /// Provides the full block via the chain::Listen interface. In the current code this is
95- /// equivalent to TransactionsFirst with some additional assertions.
97+ /// The same as `TransactionsFirst` when connecting blocks. During disconnection only
98+ /// `transaction_unconfirmed` is called.
99+ TransactionsFirstReorgsOnlyTip ,
100+ /// Provides the full block via the `chain::Listen` interface. In the current code this is
101+ /// equivalent to `TransactionsFirst` with some additional assertions.
96102 FullBlockViaListen ,
97103}
98104
105+ impl ConnectStyle {
106+ fn random_style ( ) -> ConnectStyle {
107+ #[ cfg( feature = "std" ) ] {
108+ use core:: hash:: { BuildHasher , Hasher } ;
109+ // Get a random value using the only std API to do so - the DefaultHasher
110+ let rand_val = std:: collections:: hash_map:: RandomState :: new ( ) . build_hasher ( ) . finish ( ) ;
111+ let res = match rand_val % 7 {
112+ 0 => ConnectStyle :: BestBlockFirst ,
113+ 1 => ConnectStyle :: BestBlockFirstSkippingBlocks ,
114+ 2 => ConnectStyle :: BestBlockFirstReorgsOnlyTip ,
115+ 3 => ConnectStyle :: TransactionsFirst ,
116+ 4 => ConnectStyle :: TransactionsFirstSkippingBlocks ,
117+ 5 => ConnectStyle :: TransactionsFirstReorgsOnlyTip ,
118+ 6 => ConnectStyle :: FullBlockViaListen ,
119+ _ => unreachable ! ( ) ,
120+ } ;
121+ eprintln ! ( "Using Block Connection Style: {:?}" , res) ;
122+ res
123+ }
124+ #[ cfg( not( feature = "std" ) ) ] {
125+ ConnectStyle :: FullBlockViaListen
126+ }
127+ }
128+ }
129+
99130pub fn connect_blocks < ' a , ' b , ' c , ' d > ( node : & ' a Node < ' b , ' c , ' d > , depth : u32 ) -> BlockHash {
100131 let skip_intermediaries = match * node. connect_style . borrow ( ) {
101- ConnectStyle :: BestBlockFirstSkippingBlocks |ConnectStyle :: TransactionsFirstSkippingBlocks => true ,
132+ ConnectStyle :: BestBlockFirstSkippingBlocks |ConnectStyle :: TransactionsFirstSkippingBlocks |
133+ ConnectStyle :: BestBlockFirstReorgsOnlyTip |ConnectStyle :: TransactionsFirstReorgsOnlyTip => true ,
102134 _ => false ,
103135 } ;
104136
@@ -109,18 +141,20 @@ pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32) ->
109141 } ;
110142 assert ! ( depth >= 1 ) ;
111143 for i in 1 ..depth {
112- do_connect_block ( node, & block, skip_intermediaries) ;
144+ let prev_blockhash = block. header . block_hash ( ) ;
145+ do_connect_block ( node, block, skip_intermediaries) ;
113146 block = Block {
114- header : BlockHeader { version : 0x20000000 , prev_blockhash : block . header . block_hash ( ) , merkle_root : Default :: default ( ) , time : height + i, bits : 42 , nonce : 42 } ,
147+ header : BlockHeader { version : 0x20000000 , prev_blockhash, merkle_root : Default :: default ( ) , time : height + i, bits : 42 , nonce : 42 } ,
115148 txdata : vec ! [ ] ,
116149 } ;
117150 }
118- connect_block ( node, & block) ;
119- block. header . block_hash ( )
151+ let hash = block. header . block_hash ( ) ;
152+ do_connect_block ( node, block, false ) ;
153+ hash
120154}
121155
122156pub fn connect_block < ' a , ' b , ' c , ' d > ( node : & ' a Node < ' b , ' c , ' d > , block : & Block ) {
123- do_connect_block ( node, block, false ) ;
157+ do_connect_block ( node, block. clone ( ) , false ) ;
124158}
125159
126160fn call_claimable_balances < ' a , ' b , ' c , ' d > ( node : & ' a Node < ' b , ' c , ' d > ) {
@@ -130,20 +164,23 @@ fn call_claimable_balances<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) {
130164 }
131165}
132166
133- fn do_connect_block < ' a , ' b , ' c , ' d > ( node : & ' a Node < ' b , ' c , ' d > , block : & Block , skip_intermediaries : bool ) {
167+ fn do_connect_block < ' a , ' b , ' c , ' d > ( node : & ' a Node < ' b , ' c , ' d > , block : Block , skip_intermediaries : bool ) {
134168 call_claimable_balances ( node) ;
135169 let height = node. best_block_info ( ) . 1 + 1 ;
170+ #[ cfg( feature = "std" ) ] {
171+ eprintln ! ( "Connecting block using Block Connection Style: {:?}" , * node. connect_style. borrow( ) ) ;
172+ }
136173 if !skip_intermediaries {
137174 let txdata: Vec < _ > = block. txdata . iter ( ) . enumerate ( ) . collect ( ) ;
138175 match * node. connect_style . borrow ( ) {
139- ConnectStyle :: BestBlockFirst |ConnectStyle :: BestBlockFirstSkippingBlocks => {
176+ ConnectStyle :: BestBlockFirst |ConnectStyle :: BestBlockFirstSkippingBlocks | ConnectStyle :: BestBlockFirstReorgsOnlyTip => {
140177 node. chain_monitor . chain_monitor . best_block_updated ( & block. header , height) ;
141178 call_claimable_balances ( node) ;
142179 node. chain_monitor . chain_monitor . transactions_confirmed ( & block. header , & txdata, height) ;
143180 node. node . best_block_updated ( & block. header , height) ;
144181 node. node . transactions_confirmed ( & block. header , & txdata, height) ;
145182 } ,
146- ConnectStyle :: TransactionsFirst |ConnectStyle :: TransactionsFirstSkippingBlocks => {
183+ ConnectStyle :: TransactionsFirst |ConnectStyle :: TransactionsFirstSkippingBlocks | ConnectStyle :: TransactionsFirstReorgsOnlyTip => {
147184 node. chain_monitor . chain_monitor . transactions_confirmed ( & block. header , & txdata, height) ;
148185 call_claimable_balances ( node) ;
149186 node. chain_monitor . chain_monitor . best_block_updated ( & block. header , height) ;
@@ -158,30 +195,39 @@ fn do_connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block, s
158195 }
159196 call_claimable_balances ( node) ;
160197 node. node . test_process_background_events ( ) ;
161- node. blocks . lock ( ) . unwrap ( ) . push ( ( block. header , height) ) ;
198+ node. blocks . lock ( ) . unwrap ( ) . push ( ( block, height) ) ;
162199}
163200
164201pub fn disconnect_blocks < ' a , ' b , ' c , ' d > ( node : & ' a Node < ' b , ' c , ' d > , count : u32 ) {
165202 call_claimable_balances ( node) ;
203+ #[ cfg( feature = "std" ) ] {
204+ eprintln ! ( "Disconnecting {} blocks using Block Connection Style: {:?}" , count, * node. connect_style. borrow( ) ) ;
205+ }
166206 for i in 0 ..count {
167- let orig_header = node. blocks . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
168- assert ! ( orig_header . 1 > 0 ) ; // Cannot disconnect genesis
169- let prev_header = node. blocks . lock ( ) . unwrap ( ) . last ( ) . unwrap ( ) . clone ( ) ;
207+ let orig = node. blocks . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
208+ assert ! ( orig . 1 > 0 ) ; // Cannot disconnect genesis
209+ let prev = node. blocks . lock ( ) . unwrap ( ) . last ( ) . unwrap ( ) . clone ( ) ;
170210
171211 match * node. connect_style . borrow ( ) {
172212 ConnectStyle :: FullBlockViaListen => {
173- node. chain_monitor . chain_monitor . block_disconnected ( & orig_header . 0 , orig_header . 1 ) ;
174- Listen :: block_disconnected ( node. node , & orig_header . 0 , orig_header . 1 ) ;
213+ node. chain_monitor . chain_monitor . block_disconnected ( & orig . 0 . header , orig . 1 ) ;
214+ Listen :: block_disconnected ( node. node , & orig . 0 . header , orig . 1 ) ;
175215 } ,
176216 ConnectStyle :: BestBlockFirstSkippingBlocks |ConnectStyle :: TransactionsFirstSkippingBlocks => {
177217 if i == count - 1 {
178- node. chain_monitor . chain_monitor . best_block_updated ( & prev_header. 0 , prev_header. 1 ) ;
179- node. node . best_block_updated ( & prev_header. 0 , prev_header. 1 ) ;
218+ node. chain_monitor . chain_monitor . best_block_updated ( & prev. 0 . header , prev. 1 ) ;
219+ node. node . best_block_updated ( & prev. 0 . header , prev. 1 ) ;
220+ }
221+ } ,
222+ ConnectStyle :: BestBlockFirstReorgsOnlyTip |ConnectStyle :: TransactionsFirstReorgsOnlyTip => {
223+ for tx in orig. 0 . txdata {
224+ node. chain_monitor . chain_monitor . transaction_unconfirmed ( & tx. txid ( ) ) ;
225+ node. node . transaction_unconfirmed ( & tx. txid ( ) ) ;
180226 }
181227 } ,
182228 _ => {
183- node. chain_monitor . chain_monitor . best_block_updated ( & prev_header . 0 , prev_header . 1 ) ;
184- node. node . best_block_updated ( & prev_header . 0 , prev_header . 1 ) ;
229+ node. chain_monitor . chain_monitor . best_block_updated ( & prev . 0 . header , prev . 1 ) ;
230+ node. node . best_block_updated ( & prev . 0 . header , prev . 1 ) ;
185231 } ,
186232 }
187233 call_claimable_balances ( node) ;
@@ -227,7 +273,7 @@ pub struct Node<'a, 'b: 'a, 'c: 'b> {
227273 pub network_payment_count : Rc < RefCell < u8 > > ,
228274 pub network_chan_count : Rc < RefCell < u32 > > ,
229275 pub logger : & ' c test_utils:: TestLogger ,
230- pub blocks : Arc < Mutex < Vec < ( BlockHeader , u32 ) > > > ,
276+ pub blocks : Arc < Mutex < Vec < ( Block , u32 ) > > > ,
231277 pub connect_style : Rc < RefCell < ConnectStyle > > ,
232278}
233279impl < ' a , ' b , ' c > Node < ' a , ' b , ' c > {
@@ -238,7 +284,7 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
238284 self . blocks . lock ( ) . unwrap ( ) . last ( ) . map ( |( a, b) | ( a. block_hash ( ) , * b) ) . unwrap ( )
239285 }
240286 pub fn get_block_header ( & self , height : u32 ) -> BlockHeader {
241- self . blocks . lock ( ) . unwrap ( ) [ height as usize ] . 0
287+ self . blocks . lock ( ) . unwrap ( ) [ height as usize ] . 0 . header
242288 }
243289}
244290
@@ -1821,7 +1867,7 @@ pub fn create_chanmon_cfgs(node_count: usize) -> Vec<TestChanMonCfg> {
18211867 for i in 0 ..node_count {
18221868 let tx_broadcaster = test_utils:: TestBroadcaster {
18231869 txn_broadcasted : Mutex :: new ( Vec :: new ( ) ) ,
1824- blocks : Arc :: new ( Mutex :: new ( vec ! [ ( genesis_block( Network :: Testnet ) . header , 0 ) ] ) ) ,
1870+ blocks : Arc :: new ( Mutex :: new ( vec ! [ ( genesis_block( Network :: Testnet ) , 0 ) ] ) ) ,
18251871 } ;
18261872 let fee_estimator = test_utils:: TestFeeEstimator { sat_per_kw : Mutex :: new ( 253 ) } ;
18271873 let chain_source = test_utils:: TestChainSource :: new ( Network :: Testnet ) ;
@@ -1895,7 +1941,7 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeC
18951941 let mut nodes = Vec :: new ( ) ;
18961942 let chan_count = Rc :: new ( RefCell :: new ( 0 ) ) ;
18971943 let payment_count = Rc :: new ( RefCell :: new ( 0 ) ) ;
1898- let connect_style = Rc :: new ( RefCell :: new ( ConnectStyle :: FullBlockViaListen ) ) ;
1944+ let connect_style = Rc :: new ( RefCell :: new ( ConnectStyle :: random_style ( ) ) ) ;
18991945
19001946 for i in 0 ..node_count {
19011947 let net_graph_msg_handler = NetGraphMsgHandler :: new ( cfgs[ i] . network_graph , None , cfgs[ i] . logger ) ;
0 commit comments