@@ -33,7 +33,7 @@ use secp256k1::key::{PublicKey,SecretKey};
33
33
use secp256k1:: Secp256k1 ;
34
34
35
35
use std:: cell:: RefCell ;
36
- use std:: collections:: HashMap ;
36
+ use std:: collections:: { HashMap , hash_map } ;
37
37
use std:: cmp;
38
38
use std:: hash:: Hash ;
39
39
use std:: sync:: Arc ;
@@ -140,10 +140,11 @@ struct MoneyLossDetector<'a> {
140
140
141
141
peers : & ' a RefCell < [ bool ; 256 ] > ,
142
142
funding_txn : Vec < Transaction > ,
143
+ txids_confirmed : HashMap < Sha256dHash , usize > ,
143
144
header_hashes : Vec < Sha256dHash > ,
144
145
height : usize ,
145
146
max_height : usize ,
146
-
147
+ blocks_connected : u32 ,
147
148
}
148
149
impl < ' a > MoneyLossDetector < ' a > {
149
150
pub fn new ( peers : & ' a RefCell < [ bool ; 256 ] > , manager : Arc < ChannelManager > , monitor : Arc < channelmonitor:: SimpleManyChannelMonitor < OutPoint > > , handler : PeerManager < Peer < ' a > > ) -> Self {
@@ -154,17 +155,34 @@ impl<'a> MoneyLossDetector<'a> {
154
155
155
156
peers,
156
157
funding_txn : Vec :: new ( ) ,
158
+ txids_confirmed : HashMap :: new ( ) ,
157
159
header_hashes : vec ! [ Default :: default ( ) ] ,
158
160
height : 0 ,
159
161
max_height : 0 ,
162
+ blocks_connected : 0 ,
160
163
}
161
164
}
162
165
163
- fn connect_block ( & mut self , txn : & [ & Transaction ] , txn_idxs : & [ u32 ] ) {
164
- let header = BlockHeader { version : 0x20000000 , prev_blockhash : self . header_hashes [ self . height ] , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
166
+ fn connect_block ( & mut self , all_txn : & [ Transaction ] ) {
167
+ let mut txn = Vec :: with_capacity ( all_txn. len ( ) ) ;
168
+ let mut txn_idxs = Vec :: with_capacity ( all_txn. len ( ) ) ;
169
+ for ( idx, tx) in all_txn. iter ( ) . enumerate ( ) {
170
+ let txid = Sha256dHash :: from_data ( & serialize ( tx) . unwrap ( ) [ ..] ) ;
171
+ match self . txids_confirmed . entry ( txid) {
172
+ hash_map:: Entry :: Vacant ( e) => {
173
+ e. insert ( self . height ) ;
174
+ txn. push ( tx) ;
175
+ txn_idxs. push ( idx as u32 + 1 ) ;
176
+ } ,
177
+ _ => { } ,
178
+ }
179
+ }
180
+
181
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : self . header_hashes [ self . height ] , merkle_root : Default :: default ( ) , time : self . blocks_connected , bits : 42 , nonce : 42 } ;
165
182
self . height += 1 ;
166
- self . manager . block_connected ( & header, self . height as u32 , txn, txn_idxs) ;
167
- ( * self . monitor ) . block_connected ( & header, self . height as u32 , txn, txn_idxs) ;
183
+ self . blocks_connected += 1 ;
184
+ self . manager . block_connected ( & header, self . height as u32 , & txn[ ..] , & txn_idxs[ ..] ) ;
185
+ ( * self . monitor ) . block_connected ( & header, self . height as u32 , & txn[ ..] , & txn_idxs[ ..] ) ;
168
186
if self . header_hashes . len ( ) > self . height {
169
187
self . header_hashes [ self . height ] = header. bitcoin_hash ( ) ;
170
188
} else {
@@ -180,6 +198,10 @@ impl<'a> MoneyLossDetector<'a> {
180
198
let header = BlockHeader { version : 0x20000000 , prev_blockhash : self . header_hashes [ self . height ] , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
181
199
self . manager . block_disconnected ( & header) ;
182
200
self . monitor . block_disconnected ( & header) ;
201
+ let removal_height = self . height ;
202
+ self . txids_confirmed . retain ( |_, height| {
203
+ removal_height != * height
204
+ } ) ;
183
205
}
184
206
}
185
207
}
@@ -398,36 +420,36 @@ pub fn do_test(data: &[u8], logger: &Arc<Logger>) {
398
420
}
399
421
} ,
400
422
10 => {
401
- for funding_generation in pending_funding_generation. drain ( ..) {
423
+ ' outer_loop : for funding_generation in pending_funding_generation. drain ( ..) {
402
424
let mut tx = Transaction { version : 0 , lock_time : 0 , input : Vec :: new ( ) , output : vec ! [ TxOut {
403
425
value: funding_generation. 1 , script_pubkey: funding_generation. 2 ,
404
426
} ] } ;
405
- let funding_output = OutPoint :: new ( Sha256dHash :: from_data ( & serialize ( & tx) . unwrap ( ) [ ..] ) , 0 ) ;
406
- let mut found_duplicate_txo = false ;
407
- for chan in channelmanager. list_channels ( ) {
408
- if chan. channel_id == funding_output. to_channel_id ( ) {
409
- found_duplicate_txo = true ;
427
+ let funding_output = ' search_loop: loop {
428
+ let funding_txid = Sha256dHash :: from_data ( & serialize ( & tx) . unwrap ( ) [ ..] ) ;
429
+ if let None = loss_detector. txids_confirmed . get ( & funding_txid) {
430
+ let outpoint = OutPoint :: new ( funding_txid, 0 ) ;
431
+ for chan in channelmanager. list_channels ( ) {
432
+ if chan. channel_id == outpoint. to_channel_id ( ) {
433
+ tx. version += 1 ;
434
+ continue ' search_loop;
435
+ }
436
+ }
437
+ break outpoint;
410
438
}
411
- }
412
- if !found_duplicate_txo {
413
- channelmanager. funding_transaction_generated ( & funding_generation. 0 , funding_output. clone ( ) ) ;
414
- pending_funding_signatures. insert ( funding_output, tx) ;
415
- }
439
+ tx. version += 1 ;
440
+ if tx. version > 0xff {
441
+ continue ' outer_loop;
442
+ }
443
+ } ;
444
+ channelmanager. funding_transaction_generated ( & funding_generation. 0 , funding_output. clone ( ) ) ;
445
+ pending_funding_signatures. insert ( funding_output, tx) ;
416
446
}
417
447
} ,
418
448
11 => {
419
449
if !pending_funding_relay. is_empty ( ) {
420
- let mut txn = Vec :: with_capacity ( pending_funding_relay. len ( ) ) ;
421
- let mut txn_idxs = Vec :: with_capacity ( pending_funding_relay. len ( ) ) ;
422
- for ( idx, tx) in pending_funding_relay. iter ( ) . enumerate ( ) {
423
- txn. push ( tx) ;
424
- txn_idxs. push ( idx as u32 + 1 ) ;
425
- }
426
-
427
- loss_detector. connect_block ( & txn[ ..] , & txn_idxs[ ..] ) ;
428
- txn_idxs. clear ( ) ;
450
+ loss_detector. connect_block ( & pending_funding_relay[ ..] ) ;
429
451
for _ in 2 ..100 {
430
- loss_detector. connect_block ( & txn [ .. ] , & txn_idxs [ .. ] ) ;
452
+ loss_detector. connect_block ( & [ ] ) ;
431
453
}
432
454
}
433
455
for tx in pending_funding_relay. drain ( ..) {
@@ -437,11 +459,11 @@ pub fn do_test(data: &[u8], logger: &Arc<Logger>) {
437
459
12 => {
438
460
let txlen = slice_to_be16 ( get_slice ! ( 2 ) ) ;
439
461
if txlen == 0 {
440
- loss_detector. connect_block ( & [ ] , & [ ] ) ;
462
+ loss_detector. connect_block ( & [ ] ) ;
441
463
} else {
442
464
let txres: Result < Transaction , _ > = deserialize ( get_slice ! ( txlen) ) ;
443
465
if let Ok ( tx) = txres {
444
- loss_detector. connect_block ( & [ & tx ] , & [ 1 ] ) ;
466
+ loss_detector. connect_block ( & [ tx ] ) ;
445
467
} else {
446
468
return ;
447
469
}
0 commit comments