@@ -666,7 +666,7 @@ pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
666666 // interface knows about the TXOs that we want to be notified of spends of. We could probably
667667 // be smart and derive them from the above storage fields, but its much simpler and more
668668 // 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 ) > > ,
670670
671671 #[ cfg( test) ]
672672 pub onchain_tx_handler : OnchainTxHandler < ChanSigner > ,
@@ -914,10 +914,11 @@ impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
914914 }
915915
916916 ( 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 ( ) {
918918 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) ?;
921922 script. write ( writer) ?;
922923 }
923924 }
@@ -963,7 +964,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
963964 onchain_tx_handler. provide_latest_holder_tx ( initial_holder_commitment_tx) ;
964965
965966 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( ) ) ] ) ;
967968
968969 ChannelMonitor {
969970 latest_update_id : 0 ,
@@ -1209,7 +1210,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
12091210 /// transaction), which we must learn about spends of via block_connected().
12101211 ///
12111212 /// (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 ) > > {
12131214 // If we've detected a counterparty commitment tx on chain, we must include it in the set
12141215 // of outputs to watch for spends of, otherwise we're likely to lose user funds. Because
12151216 // its trivial to do, double-check that here.
@@ -1264,7 +1265,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
12641265 /// HTLC-Success/HTLC-Timeout transactions.
12651266 /// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
12661267 /// 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 {
12681269 // Most secp and related errors trying to create keys means we have no hope of constructing
12691270 // a spend transaction...so we return no transactions to broadcast
12701271 let mut claimable_outpoints = Vec :: new ( ) ;
@@ -1319,7 +1320,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
13191320 if !claimable_outpoints. is_empty ( ) || per_commitment_option. is_some ( ) { // ie we're confident this is actually ours
13201321 // We're definitely a counterparty commitment transaction!
13211322 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+ }
13231326 self . counterparty_commitment_txn_on_chain . insert ( commitment_txid, commitment_number) ;
13241327
13251328 macro_rules! check_htlc_fails {
@@ -1366,7 +1369,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
13661369 // already processed the block, resulting in the counterparty_commitment_txn_on_chain entry
13671370 // not being generated by the above conditional. Thus, to be safe, we go ahead and
13681371 // 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+ }
13701375 self . counterparty_commitment_txn_on_chain . insert ( commitment_txid, commitment_number) ;
13711376
13721377 log_trace ! ( logger, "Got broadcast of non-revoked counterparty commitment transaction {}" , commitment_txid) ;
@@ -1456,7 +1461,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14561461 }
14571462
14581463 /// 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 {
14601465 let htlc_txid = tx. txid ( ) ;
14611466 if tx. input . len ( ) != 1 || tx. output . len ( ) != 1 || tx. input [ 0 ] . witness . len ( ) != 5 {
14621467 return ( Vec :: new ( ) , None )
@@ -1478,10 +1483,11 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
14781483 log_trace ! ( logger, "Counterparty HTLC broadcast {}:{}" , htlc_txid, 0 ) ;
14791484 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 } ;
14801485 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) ) )
14821488 }
14831489
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 ) > ) {
14851491 let mut claim_requests = Vec :: with_capacity ( holder_tx. htlc_outputs . len ( ) ) ;
14861492 let mut watch_outputs = Vec :: with_capacity ( holder_tx. htlc_outputs . len ( ) ) ;
14871493
@@ -1502,7 +1508,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
15021508 } else { None } ,
15031509 amount : htlc. amount_msat ,
15041510 } } ) ;
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 ( ) ) ) ;
15061512 }
15071513 }
15081514
@@ -1512,7 +1518,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
15121518 /// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
15131519 /// revoked using data in holder_claimable_outpoints.
15141520 /// 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 {
15161522 let commitment_txid = tx. txid ( ) ;
15171523 let mut claim_requests = Vec :: new ( ) ;
15181524 let mut watch_outputs = Vec :: new ( ) ;
@@ -1662,7 +1668,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
16621668 /// [`get_outputs_to_watch`].
16631669 ///
16641670 /// [`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 ) > ) >
16661672 where B :: Target : BroadcasterInterface ,
16671673 F :: Target : FeeEstimator ,
16681674 L :: Target : Logger ,
@@ -1763,9 +1769,23 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
17631769 // Determine new outputs to watch by comparing against previously known outputs to watch,
17641770 // updating the latter in the process.
17651771 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 ( )
17681774 } ) ;
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+ }
17691789 watch_outputs
17701790 }
17711791
@@ -1813,8 +1833,19 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
18131833 fn spends_watched_output ( & self , tx : & Transaction ) -> bool {
18141834 for input in tx. input . iter ( ) {
18151835 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+ }
18181849 return true ;
18191850 }
18201851 }
@@ -2316,13 +2347,13 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for (BlockHash, ChannelMonitor
23162347 }
23172348
23182349 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 > > ( ) ) ) ) ;
23202351 for _ in 0 ..outputs_to_watch_len {
23212352 let txid = Readable :: read ( reader) ?;
23222353 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 > ( ) ) ) ) ;
23242355 for _ in 0 ..outputs_len {
2325- outputs. push ( Readable :: read ( reader) ?) ;
2356+ outputs. push ( ( Readable :: read ( reader) ?, Readable :: read ( reader ) ? ) ) ;
23262357 }
23272358 if let Some ( _) = outputs_to_watch. insert ( txid, outputs) {
23282359 return Err ( DecodeError :: InvalidValue ) ;
0 commit comments