@@ -666,7 +666,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
666
666
// interface knows about the TXOs that we want to be notified of spends of. We could probably
667
667
// be smart and derive them from the above storage fields, but its much simpler and more
668
668
// Obviously Correct (tm) if we just keep track of them explicitly.
669
- outputs_to_watch : HashMap < Txid , Vec < Script > > ,
669
+ outputs_to_watch : HashMap < Txid , Vec < ( u32 , Script ) > > ,
670
670
671
671
#[ cfg( test) ]
672
672
pub onchain_tx_handler : OnchainTxHandler < ChanSigner > ,
@@ -914,10 +914,11 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
914
914
}
915
915
916
916
( self . outputs_to_watch . len ( ) as u64 ) . write ( writer) ?;
917
- for ( txid, output_scripts ) in self . outputs_to_watch . iter ( ) {
917
+ for ( txid, idx_scripts ) in self . outputs_to_watch . iter ( ) {
918
918
txid. write ( writer) ?;
919
- ( output_scripts. len ( ) as u64 ) . write ( writer) ?;
920
- for script in output_scripts. iter ( ) {
919
+ ( idx_scripts. len ( ) as u64 ) . write ( writer) ?;
920
+ for ( idx, script) in idx_scripts. iter ( ) {
921
+ idx. write ( writer) ?;
921
922
script. write ( writer) ?;
922
923
}
923
924
}
@@ -963,7 +964,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
963
964
onchain_tx_handler. provide_latest_holder_tx ( initial_holder_commitment_tx) ;
964
965
965
966
let mut outputs_to_watch = HashMap :: new ( ) ;
966
- outputs_to_watch. insert ( funding_info. 0 . txid , vec ! [ funding_info. 1 . clone( ) ] ) ;
967
+ outputs_to_watch. insert ( funding_info. 0 . txid , vec ! [ ( funding_info. 0 . index as u32 , funding_info . 1 . clone( ) ) ] ) ;
967
968
968
969
ChannelMonitor {
969
970
latest_update_id : 0 ,
@@ -1209,7 +1210,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1209
1210
/// transaction), which we must learn about spends of via block_connected().
1210
1211
///
1211
1212
/// (C-not exported) because we have no HashMap bindings
1212
- pub fn get_outputs_to_watch ( & self ) -> & HashMap < Txid , Vec < Script > > {
1213
+ pub fn get_outputs_to_watch ( & self ) -> & HashMap < Txid , Vec < ( u32 , Script ) > > {
1213
1214
// If we've detected a counterparty commitment tx on chain, we must include it in the set
1214
1215
// of outputs to watch for spends of, otherwise we're likely to lose user funds. Because
1215
1216
// its trivial to do, double-check that here.
@@ -1264,7 +1265,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1264
1265
/// HTLC-Success/HTLC-Timeout transactions.
1265
1266
/// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
1266
1267
/// revoked counterparty commitment tx
1267
- fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L ) -> ( Vec < ClaimRequest > , ( Txid , Vec < TxOut > ) ) where L :: Target : Logger {
1268
+ fn check_spend_counterparty_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L ) -> ( Vec < ClaimRequest > , ( Txid , Vec < ( u32 , TxOut ) > ) ) where L :: Target : Logger {
1268
1269
// Most secp and related errors trying to create keys means we have no hope of constructing
1269
1270
// a spend transaction...so we return no transactions to broadcast
1270
1271
let mut claimable_outpoints = Vec :: new ( ) ;
@@ -1319,7 +1320,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1319
1320
if !claimable_outpoints. is_empty ( ) || per_commitment_option. is_some ( ) { // ie we're confident this is actually ours
1320
1321
// We're definitely a counterparty commitment transaction!
1321
1322
log_trace ! ( logger, "Got broadcast of revoked counterparty commitment transaction, going to generate general spend tx with {} inputs" , claimable_outpoints. len( ) ) ;
1322
- watch_outputs. append ( & mut tx. output . clone ( ) ) ;
1323
+ for ( idx, outp) in tx. output . iter ( ) . enumerate ( ) {
1324
+ watch_outputs. push ( ( idx as u32 , outp. clone ( ) ) ) ;
1325
+ }
1323
1326
self . counterparty_commitment_txn_on_chain . insert ( commitment_txid, commitment_number) ;
1324
1327
1325
1328
macro_rules! check_htlc_fails {
@@ -1366,7 +1369,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1366
1369
// already processed the block, resulting in the counterparty_commitment_txn_on_chain entry
1367
1370
// not being generated by the above conditional. Thus, to be safe, we go ahead and
1368
1371
// insert it here.
1369
- watch_outputs. append ( & mut tx. output . clone ( ) ) ;
1372
+ for ( idx, outp) in tx. output . iter ( ) . enumerate ( ) {
1373
+ watch_outputs. push ( ( idx as u32 , outp. clone ( ) ) ) ;
1374
+ }
1370
1375
self . counterparty_commitment_txn_on_chain . insert ( commitment_txid, commitment_number) ;
1371
1376
1372
1377
log_trace ! ( logger, "Got broadcast of non-revoked counterparty commitment transaction {}" , commitment_txid) ;
@@ -1456,7 +1461,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1456
1461
}
1457
1462
1458
1463
/// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key
1459
- fn check_spend_counterparty_htlc < L : Deref > ( & mut self , tx : & Transaction , commitment_number : u64 , height : u32 , logger : & L ) -> ( Vec < ClaimRequest > , Option < ( Txid , Vec < TxOut > ) > ) where L :: Target : Logger {
1464
+ fn check_spend_counterparty_htlc < L : Deref > ( & mut self , tx : & Transaction , commitment_number : u64 , height : u32 , logger : & L ) -> ( Vec < ClaimRequest > , Option < ( Txid , Vec < ( u32 , TxOut ) > ) > ) where L :: Target : Logger {
1460
1465
let htlc_txid = tx. txid ( ) ;
1461
1466
if tx. input . len ( ) != 1 || tx. output . len ( ) != 1 || tx. input [ 0 ] . witness . len ( ) != 5 {
1462
1467
return ( Vec :: new ( ) , None )
@@ -1478,10 +1483,11 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1478
1483
log_trace ! ( logger, "Counterparty HTLC broadcast {}:{}" , htlc_txid, 0 ) ;
1479
1484
let witness_data = InputMaterial :: Revoked { per_commitment_point, counterparty_delayed_payment_base_key : self . counterparty_tx_cache . counterparty_delayed_payment_base_key , counterparty_htlc_base_key : self . counterparty_tx_cache . counterparty_htlc_base_key , per_commitment_key, input_descriptor : InputDescriptors :: RevokedOutput , amount : tx. output [ 0 ] . value , htlc : None , on_counterparty_tx_csv : self . counterparty_tx_cache . on_counterparty_tx_csv } ;
1480
1485
let claimable_outpoints = vec ! ( ClaimRequest { absolute_timelock: height + self . counterparty_tx_cache. on_counterparty_tx_csv as u32 , aggregable: true , outpoint: BitcoinOutPoint { txid: htlc_txid, vout: 0 } , witness_data } ) ;
1481
- ( claimable_outpoints, Some ( ( htlc_txid, tx. output . clone ( ) ) ) )
1486
+ let outputs = vec ! [ ( 0 , tx. output[ 0 ] . clone( ) ) ] ;
1487
+ ( claimable_outpoints, Some ( ( htlc_txid, outputs) ) )
1482
1488
}
1483
1489
1484
- fn broadcast_by_holder_state ( & self , commitment_tx : & Transaction , holder_tx : & HolderSignedTx ) -> ( Vec < ClaimRequest > , Vec < TxOut > , Option < ( Script , PublicKey , PublicKey ) > ) {
1490
+ fn broadcast_by_holder_state ( & self , commitment_tx : & Transaction , holder_tx : & HolderSignedTx ) -> ( Vec < ClaimRequest > , Vec < ( u32 , TxOut ) > , Option < ( Script , PublicKey , PublicKey ) > ) {
1485
1491
let mut claim_requests = Vec :: with_capacity ( holder_tx. htlc_outputs . len ( ) ) ;
1486
1492
let mut watch_outputs = Vec :: with_capacity ( holder_tx. htlc_outputs . len ( ) ) ;
1487
1493
@@ -1502,7 +1508,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1502
1508
} else { None } ,
1503
1509
amount : htlc. amount_msat ,
1504
1510
} } ) ;
1505
- watch_outputs. push ( commitment_tx. output [ transaction_output_index as usize ] . clone ( ) ) ;
1511
+ watch_outputs. push ( ( transaction_output_index , commitment_tx. output [ transaction_output_index as usize ] . clone ( ) ) ) ;
1506
1512
}
1507
1513
}
1508
1514
@@ -1512,7 +1518,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1512
1518
/// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
1513
1519
/// revoked using data in holder_claimable_outpoints.
1514
1520
/// Should not be used if check_spend_revoked_transaction succeeds.
1515
- fn check_spend_holder_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L ) -> ( Vec < ClaimRequest > , ( Txid , Vec < TxOut > ) ) where L :: Target : Logger {
1521
+ fn check_spend_holder_transaction < L : Deref > ( & mut self , tx : & Transaction , height : u32 , logger : & L ) -> ( Vec < ClaimRequest > , ( Txid , Vec < ( u32 , TxOut ) > ) ) where L :: Target : Logger {
1516
1522
let commitment_txid = tx. txid ( ) ;
1517
1523
let mut claim_requests = Vec :: new ( ) ;
1518
1524
let mut watch_outputs = Vec :: new ( ) ;
@@ -1662,7 +1668,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1662
1668
/// [`get_outputs_to_watch`].
1663
1669
///
1664
1670
/// [`get_outputs_to_watch`]: #method.get_outputs_to_watch
1665
- pub fn block_connected < B : Deref , F : Deref , L : Deref > ( & mut self , header : & BlockHeader , txdata : & TransactionData , height : u32 , broadcaster : B , fee_estimator : F , logger : L ) -> Vec < ( Txid , Vec < TxOut > ) >
1671
+ pub fn block_connected < B : Deref , F : Deref , L : Deref > ( & mut self , header : & BlockHeader , txdata : & TransactionData , height : u32 , broadcaster : B , fee_estimator : F , logger : L ) -> Vec < ( Txid , Vec < ( u32 , TxOut ) > ) >
1666
1672
where B :: Target : BroadcasterInterface ,
1667
1673
F :: Target : FeeEstimator ,
1668
1674
L :: Target : Logger ,
@@ -1763,9 +1769,23 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1763
1769
// Determine new outputs to watch by comparing against previously known outputs to watch,
1764
1770
// updating the latter in the process.
1765
1771
watch_outputs. retain ( |& ( ref txid, ref txouts) | {
1766
- let output_scripts = txouts. iter ( ) . map ( |o| o . script_pubkey . clone ( ) ) . collect ( ) ;
1767
- self . outputs_to_watch . insert ( txid. clone ( ) , output_scripts ) . is_none ( )
1772
+ let idx_and_scripts = txouts. iter ( ) . map ( |o| ( o . 0 , o . 1 . script_pubkey . clone ( ) ) ) . collect ( ) ;
1773
+ self . outputs_to_watch . insert ( txid. clone ( ) , idx_and_scripts ) . is_none ( )
1768
1774
} ) ;
1775
+ #[ cfg( test) ]
1776
+ {
1777
+ // If we see a transaction for which we registered outputs previously,
1778
+ // make sure the registered scriptpubkey at the expected index match
1779
+ // the actual transaction output one. We failed this case before #653.
1780
+ for tx in & txn_matched {
1781
+ if let Some ( outputs) = self . get_outputs_to_watch ( ) . get ( & tx. txid ( ) ) {
1782
+ for idx_and_script in outputs. iter ( ) {
1783
+ assert ! ( ( idx_and_script. 0 as usize ) < tx. output. len( ) ) ;
1784
+ assert_eq ! ( tx. output[ idx_and_script. 0 as usize ] . script_pubkey, idx_and_script. 1 ) ;
1785
+ }
1786
+ }
1787
+ }
1788
+ }
1769
1789
watch_outputs
1770
1790
}
1771
1791
@@ -1813,8 +1833,19 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1813
1833
fn spends_watched_output ( & self , tx : & Transaction ) -> bool {
1814
1834
for input in tx. input . iter ( ) {
1815
1835
if let Some ( outputs) = self . get_outputs_to_watch ( ) . get ( & input. previous_output . txid ) {
1816
- for ( idx, _script_pubkey) in outputs. iter ( ) . enumerate ( ) {
1817
- if idx == input. previous_output . vout as usize {
1836
+ for ( idx, _script_pubkey) in outputs. iter ( ) {
1837
+ if * idx == input. previous_output . vout {
1838
+ #[ cfg( test) ]
1839
+ {
1840
+ // If the expected script is a known type, check that the witness
1841
+ // appears to be spending the correct type (ie that the match would
1842
+ // actually succeed in BIP 158/159-style filters).
1843
+ if _script_pubkey. is_v0_p2wsh ( ) {
1844
+ assert_eq ! ( & bitcoin:: Address :: p2wsh( & Script :: from( input. witness. last( ) . unwrap( ) . clone( ) ) , bitcoin:: Network :: Bitcoin ) . script_pubkey( ) , _script_pubkey) ;
1845
+ } else if _script_pubkey. is_v0_p2wpkh ( ) {
1846
+ assert_eq ! ( & bitcoin:: Address :: p2wpkh( & bitcoin:: PublicKey :: from_slice( & input. witness. last( ) . unwrap( ) ) . unwrap( ) , bitcoin:: Network :: Bitcoin ) . unwrap( ) . script_pubkey( ) , _script_pubkey) ;
1847
+ } else { panic ! ( ) ; }
1848
+ }
1818
1849
return true ;
1819
1850
}
1820
1851
}
@@ -2316,13 +2347,13 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for (BlockHash, ChannelMonitor
2316
2347
}
2317
2348
2318
2349
let outputs_to_watch_len: u64 = Readable :: read ( reader) ?;
2319
- let mut outputs_to_watch = HashMap :: with_capacity ( cmp:: min ( outputs_to_watch_len as usize , MAX_ALLOC_SIZE / ( mem:: size_of :: < Txid > ( ) + mem:: size_of :: < Vec < Script > > ( ) ) ) ) ;
2350
+ let mut outputs_to_watch = HashMap :: with_capacity ( cmp:: min ( outputs_to_watch_len as usize , MAX_ALLOC_SIZE / ( mem:: size_of :: < Txid > ( ) + mem:: size_of :: < u32 > ( ) + mem :: size_of :: < Vec < Script > > ( ) ) ) ) ;
2320
2351
for _ in 0 ..outputs_to_watch_len {
2321
2352
let txid = Readable :: read ( reader) ?;
2322
2353
let outputs_len: u64 = Readable :: read ( reader) ?;
2323
- let mut outputs = Vec :: with_capacity ( cmp:: min ( outputs_len as usize , MAX_ALLOC_SIZE / mem:: size_of :: < Script > ( ) ) ) ;
2354
+ let mut outputs = Vec :: with_capacity ( cmp:: min ( outputs_len as usize , MAX_ALLOC_SIZE / ( mem:: size_of :: < u32 > ( ) + mem :: size_of :: < Script > ( ) ) ) ) ;
2324
2355
for _ in 0 ..outputs_len {
2325
- outputs. push ( Readable :: read ( reader) ?) ;
2356
+ outputs. push ( ( Readable :: read ( reader) ?, Readable :: read ( reader ) ? ) ) ;
2326
2357
}
2327
2358
if let Some ( _) = outputs_to_watch. insert ( txid, outputs) {
2328
2359
return Err ( DecodeError :: InvalidValue ) ;
0 commit comments