@@ -77,28 +77,60 @@ pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &T
77
77
}
78
78
79
79
/// The possible ways we may notify a ChannelManager of a new block
80
- #[ derive( Clone , Copy , PartialEq ) ]
80
+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
81
81
pub 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.
84
84
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.
87
87
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.
90
93
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.
93
96
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.
96
102
FullBlockViaListen ,
97
103
}
98
104
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
+
99
130
pub fn connect_blocks < ' a , ' b , ' c , ' d > ( node : & ' a Node < ' b , ' c , ' d > , depth : u32 ) -> BlockHash {
100
131
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 ,
102
134
_ => false ,
103
135
} ;
104
136
@@ -109,18 +141,20 @@ pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32) ->
109
141
} ;
110
142
assert ! ( depth >= 1 ) ;
111
143
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) ;
113
146
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 } ,
115
148
txdata : vec ! [ ] ,
116
149
} ;
117
150
}
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
120
154
}
121
155
122
156
pub 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 ) ;
124
158
}
125
159
126
160
fn 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>) {
130
164
}
131
165
}
132
166
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 ) {
134
168
call_claimable_balances ( node) ;
135
169
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
+ }
136
173
if !skip_intermediaries {
137
174
let txdata: Vec < _ > = block. txdata . iter ( ) . enumerate ( ) . collect ( ) ;
138
175
match * node. connect_style . borrow ( ) {
139
- ConnectStyle :: BestBlockFirst |ConnectStyle :: BestBlockFirstSkippingBlocks => {
176
+ ConnectStyle :: BestBlockFirst |ConnectStyle :: BestBlockFirstSkippingBlocks | ConnectStyle :: BestBlockFirstReorgsOnlyTip => {
140
177
node. chain_monitor . chain_monitor . best_block_updated ( & block. header , height) ;
141
178
call_claimable_balances ( node) ;
142
179
node. chain_monitor . chain_monitor . transactions_confirmed ( & block. header , & txdata, height) ;
143
180
node. node . best_block_updated ( & block. header , height) ;
144
181
node. node . transactions_confirmed ( & block. header , & txdata, height) ;
145
182
} ,
146
- ConnectStyle :: TransactionsFirst |ConnectStyle :: TransactionsFirstSkippingBlocks => {
183
+ ConnectStyle :: TransactionsFirst |ConnectStyle :: TransactionsFirstSkippingBlocks | ConnectStyle :: TransactionsFirstReorgsOnlyTip => {
147
184
node. chain_monitor . chain_monitor . transactions_confirmed ( & block. header , & txdata, height) ;
148
185
call_claimable_balances ( node) ;
149
186
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
158
195
}
159
196
call_claimable_balances ( node) ;
160
197
node. node . test_process_background_events ( ) ;
161
- node. blocks . lock ( ) . unwrap ( ) . push ( ( block. header , height) ) ;
198
+ node. blocks . lock ( ) . unwrap ( ) . push ( ( block, height) ) ;
162
199
}
163
200
164
201
pub fn disconnect_blocks < ' a , ' b , ' c , ' d > ( node : & ' a Node < ' b , ' c , ' d > , count : u32 ) {
165
202
call_claimable_balances ( node) ;
203
+ #[ cfg( feature = "std" ) ] {
204
+ eprintln ! ( "Disconnecting {} blocks using Block Connection Style: {:?}" , count, * node. connect_style. borrow( ) ) ;
205
+ }
166
206
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 ( ) ;
170
210
171
211
match * node. connect_style . borrow ( ) {
172
212
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 ) ;
175
215
} ,
176
216
ConnectStyle :: BestBlockFirstSkippingBlocks |ConnectStyle :: TransactionsFirstSkippingBlocks => {
177
217
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 ( ) ) ;
180
226
}
181
227
} ,
182
228
_ => {
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 ) ;
185
231
} ,
186
232
}
187
233
call_claimable_balances ( node) ;
@@ -227,7 +273,7 @@ pub struct Node<'a, 'b: 'a, 'c: 'b> {
227
273
pub network_payment_count : Rc < RefCell < u8 > > ,
228
274
pub network_chan_count : Rc < RefCell < u32 > > ,
229
275
pub logger : & ' c test_utils:: TestLogger ,
230
- pub blocks : Arc < Mutex < Vec < ( BlockHeader , u32 ) > > > ,
276
+ pub blocks : Arc < Mutex < Vec < ( Block , u32 ) > > > ,
231
277
pub connect_style : Rc < RefCell < ConnectStyle > > ,
232
278
}
233
279
impl < ' a , ' b , ' c > Node < ' a , ' b , ' c > {
@@ -238,7 +284,7 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> {
238
284
self . blocks . lock ( ) . unwrap ( ) . last ( ) . map ( |( a, b) | ( a. block_hash ( ) , * b) ) . unwrap ( )
239
285
}
240
286
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
242
288
}
243
289
}
244
290
@@ -1821,7 +1867,7 @@ pub fn create_chanmon_cfgs(node_count: usize) -> Vec<TestChanMonCfg> {
1821
1867
for i in 0 ..node_count {
1822
1868
let tx_broadcaster = test_utils:: TestBroadcaster {
1823
1869
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 ) ] ) ) ,
1825
1871
} ;
1826
1872
let fee_estimator = test_utils:: TestFeeEstimator { sat_per_kw : Mutex :: new ( 253 ) } ;
1827
1873
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
1895
1941
let mut nodes = Vec :: new ( ) ;
1896
1942
let chan_count = Rc :: new ( RefCell :: new ( 0 ) ) ;
1897
1943
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 ( ) ) ) ;
1899
1945
1900
1946
for i in 0 ..node_count {
1901
1947
let net_graph_msg_handler = NetGraphMsgHandler :: new ( cfgs[ i] . network_graph , None , cfgs[ i] . logger ) ;
0 commit comments