@@ -46,6 +46,8 @@ pub enum ChannelMonitorUpdateErr {
46
46
/// channel's monitor everywhere (including remote watchtowers) *before* this function returns. If
47
47
/// an update occurs and a remote watchtower is left with old state, it may broadcast transactions
48
48
/// which we have revoked, allowing our counterparty to claim all funds in the channel!
49
+ /// A call to add_update_monitor is needed to register outpoint and its txid with ChainWatchInterface
50
+ /// after setting funding_txo in a ChannelMonitor
49
51
pub trait ManyChannelMonitor : Send + Sync {
50
52
/// Adds or updates a monitor for the given `funding_txo`.
51
53
fn add_update_monitor ( & self , funding_txo : OutPoint , monitor : ChannelMonitor ) -> Result < ( ) , ChannelMonitorUpdateErr > ;
@@ -69,7 +71,12 @@ impl<Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonit
69
71
fn block_connected ( & self , _header : & BlockHeader , height : u32 , txn_matched : & [ & Transaction ] , _indexes_of_txn_matched : & [ u32 ] ) {
70
72
let monitors = self . monitors . lock ( ) . unwrap ( ) ;
71
73
for monitor in monitors. values ( ) {
72
- monitor. block_connected ( txn_matched, height, & * self . broadcaster ) ;
74
+ let txn_outputs = monitor. block_connected ( txn_matched, height, & * self . broadcaster ) ;
75
+ for ( ref txid, ref outputs) in txn_outputs {
76
+ for ( idx, output) in outputs. iter ( ) . enumerate ( ) {
77
+ self . chain_monitor . install_watch_outpoint ( ( txid. clone ( ) , idx as u32 ) , & output. script_pubkey ) ;
78
+ }
79
+ }
73
80
}
74
81
}
75
82
@@ -97,7 +104,7 @@ impl<Key : Send + cmp::Eq + hash::Hash + 'static> SimpleManyChannelMonitor<Key>
97
104
match & monitor. funding_txo {
98
105
& None => self . chain_monitor . watch_all_txn ( ) ,
99
106
& Some ( ( ref outpoint, ref script) ) => {
100
- self . chain_monitor . install_watch_script ( script) ;
107
+ self . chain_monitor . install_watch_tx ( & outpoint . txid , script) ;
101
108
self . chain_monitor . install_watch_outpoint ( ( outpoint. txid , outpoint. index as u32 ) , script) ;
102
109
} ,
103
110
}
@@ -464,8 +471,9 @@ impl ChannelMonitor {
464
471
/// optional, without it this monitor cannot be used in an SPV client, but you may wish to
465
472
/// avoid this (or call unset_funding_info) on a monitor you wish to send to a watchtower as it
466
473
/// provides slightly better privacy.
474
+ /// It's the responsability of the caller to register outpoint and script with passing the former
475
+ /// value as key to add_update_monitor.
467
476
pub ( super ) fn set_funding_info ( & mut self , funding_info : ( OutPoint , Script ) ) {
468
- //TODO: Need to register the given script here with a chain_monitor
469
477
self . funding_txo = Some ( funding_info) ;
470
478
}
471
479
@@ -908,22 +916,24 @@ impl ChannelMonitor {
908
916
/// height > height + CLTV_SHARED_CLAIM_BUFFER. In any case, will install monitoring for
909
917
/// HTLC-Success/HTLC-Timeout transactions, and claim them using the revocation key (if
910
918
/// applicable) as well.
911
- fn check_spend_remote_transaction ( & self , tx : & Transaction , height : u32 ) -> Vec < Transaction > {
919
+ fn check_spend_remote_transaction ( & self , tx : & Transaction , height : u32 ) -> ( Vec < Transaction > , ( Sha256dHash , Vec < TxOut > ) ) {
912
920
// Most secp and related errors trying to create keys means we have no hope of constructing
913
921
// a spend transaction...so we return no transactions to broadcast
914
922
let mut txn_to_broadcast = Vec :: new ( ) ;
923
+ let mut watch_outputs = Vec :: new ( ) ;
924
+
925
+ let commitment_txid = tx. txid ( ) ; //TODO: This is gonna be a performance bottleneck for watchtowers!
926
+ let per_commitment_option = self . remote_claimable_outpoints . get ( & commitment_txid) ;
927
+
915
928
macro_rules! ignore_error {
916
929
( $thing : expr ) => {
917
930
match $thing {
918
931
Ok ( a) => a,
919
- Err ( _) => return txn_to_broadcast
932
+ Err ( _) => return ( txn_to_broadcast, ( commitment_txid , watch_outputs ) )
920
933
}
921
934
} ;
922
935
}
923
936
924
- let commitment_txid = tx. txid ( ) ; //TODO: This is gonna be a performance bottleneck for watchtowers!
925
- let per_commitment_option = self . remote_claimable_outpoints . get ( & commitment_txid) ;
926
-
927
937
let commitment_number = 0xffffffffffff - ( ( ( ( tx. input [ 0 ] . sequence as u64 & 0xffffff ) << 3 * 8 ) | ( tx. lock_time as u64 & 0xffffff ) ) ^ self . commitment_transaction_number_obscure_factor ) ;
928
938
if commitment_number >= self . get_min_seen_secret ( ) {
929
939
let secret = self . get_secret ( commitment_number) . unwrap ( ) ;
@@ -942,7 +952,7 @@ impl ChannelMonitor {
942
952
} ;
943
953
let delayed_key = ignore_error ! ( chan_utils:: derive_public_key( & self . secp_ctx, & PublicKey :: from_secret_key( & self . secp_ctx, & per_commitment_key) , & self . delayed_payment_base_key) ) ;
944
954
let a_htlc_key = match self . their_htlc_base_key {
945
- None => return txn_to_broadcast,
955
+ None => return ( txn_to_broadcast, ( commitment_txid , watch_outputs ) ) ,
946
956
Some ( their_htlc_base_key) => ignore_error ! ( chan_utils:: derive_public_key( & self . secp_ctx, & PublicKey :: from_secret_key( & self . secp_ctx, & per_commitment_key) , & their_htlc_base_key) ) ,
947
957
} ;
948
958
@@ -1009,7 +1019,7 @@ impl ChannelMonitor {
1009
1019
if htlc. transaction_output_index as usize >= tx. output . len ( ) ||
1010
1020
tx. output [ htlc. transaction_output_index as usize ] . value != htlc. amount_msat / 1000 ||
1011
1021
tx. output [ htlc. transaction_output_index as usize ] . script_pubkey != expected_script. to_v0_p2wsh ( ) {
1012
- return txn_to_broadcast; // Corrupted per_commitment_data, fuck this user
1022
+ return ( txn_to_broadcast, ( commitment_txid , watch_outputs ) ) ; // Corrupted per_commitment_data, fuck this user
1013
1023
}
1014
1024
let input = TxIn {
1015
1025
previous_output : BitcoinOutPoint {
@@ -1044,10 +1054,10 @@ impl ChannelMonitor {
1044
1054
1045
1055
if !inputs. is_empty ( ) || !txn_to_broadcast. is_empty ( ) { // ie we're confident this is actually ours
1046
1056
// We're definitely a remote commitment transaction!
1047
- // TODO: Register all outputs in commitment_tx with the ChainWatchInterface!
1057
+ watch_outputs . append ( & mut tx . output . clone ( ) ) ;
1048
1058
self . remote_commitment_txn_on_chain . lock ( ) . unwrap ( ) . insert ( commitment_txid, commitment_number) ;
1049
1059
}
1050
- if inputs. is_empty ( ) { return txn_to_broadcast; } // Nothing to be done...probably a false positive/local tx
1060
+ if inputs. is_empty ( ) { return ( txn_to_broadcast, ( commitment_txid , watch_outputs ) ) ; } // Nothing to be done...probably a false positive/local tx
1051
1061
1052
1062
let outputs = vec ! ( TxOut {
1053
1063
script_pubkey: self . destination_script. clone( ) ,
@@ -1077,7 +1087,7 @@ impl ChannelMonitor {
1077
1087
// already processed the block, resulting in the remote_commitment_txn_on_chain entry
1078
1088
// not being generated by the above conditional. Thus, to be safe, we go ahead and
1079
1089
// insert it here.
1080
- // TODO: Register all outputs in commitment_tx with the ChainWatchInterface!
1090
+ watch_outputs . append ( & mut tx . output . clone ( ) ) ;
1081
1091
self . remote_commitment_txn_on_chain . lock ( ) . unwrap ( ) . insert ( commitment_txid, commitment_number) ;
1082
1092
1083
1093
if let Some ( revocation_points) = self . their_cur_revocation_points {
@@ -1098,7 +1108,7 @@ impl ChannelMonitor {
1098
1108
} ,
1099
1109
} ;
1100
1110
let a_htlc_key = match self . their_htlc_base_key {
1101
- None => return txn_to_broadcast,
1111
+ None => return ( txn_to_broadcast, ( commitment_txid , watch_outputs ) ) ,
1102
1112
Some ( their_htlc_base_key) => ignore_error ! ( chan_utils:: derive_public_key( & self . secp_ctx, revocation_point, & their_htlc_base_key) ) ,
1103
1113
} ;
1104
1114
@@ -1161,7 +1171,7 @@ impl ChannelMonitor {
1161
1171
}
1162
1172
}
1163
1173
1164
- if inputs. is_empty ( ) { return txn_to_broadcast; } // Nothing to be done...probably a false positive/local tx
1174
+ if inputs. is_empty ( ) { return ( txn_to_broadcast, ( commitment_txid , watch_outputs ) ) ; } // Nothing to be done...probably a false positive/local tx
1165
1175
1166
1176
let outputs = vec ! ( TxOut {
1167
1177
script_pubkey: self . destination_script. clone( ) ,
@@ -1189,7 +1199,7 @@ impl ChannelMonitor {
1189
1199
//TODO: For each input check if its in our remote_commitment_txn_on_chain map!
1190
1200
}
1191
1201
1192
- txn_to_broadcast
1202
+ ( txn_to_broadcast, ( commitment_txid , watch_outputs ) )
1193
1203
}
1194
1204
1195
1205
fn broadcast_by_local_state ( & self , local_tx : & LocalSignedTx ) -> Vec < Transaction > {
@@ -1250,11 +1260,15 @@ impl ChannelMonitor {
1250
1260
Vec :: new ( )
1251
1261
}
1252
1262
1253
- fn block_connected ( & self , txn_matched : & [ & Transaction ] , height : u32 , broadcaster : & BroadcasterInterface ) {
1263
+ fn block_connected ( & self , txn_matched : & [ & Transaction ] , height : u32 , broadcaster : & BroadcasterInterface ) -> Vec < ( Sha256dHash , Vec < TxOut > ) > {
1264
+ let mut watch_outputs = Vec :: new ( ) ;
1254
1265
for tx in txn_matched {
1255
1266
for txin in tx. input . iter ( ) {
1256
1267
if self . funding_txo . is_none ( ) || ( txin. previous_output . txid == self . funding_txo . as_ref ( ) . unwrap ( ) . 0 . txid && txin. previous_output . vout == self . funding_txo . as_ref ( ) . unwrap ( ) . 0 . index as u32 ) {
1257
- let mut txn = self . check_spend_remote_transaction ( tx, height) ;
1268
+ let ( mut txn, new_outputs) = self . check_spend_remote_transaction ( tx, height) ;
1269
+ if !new_outputs. 1 . is_empty ( ) {
1270
+ watch_outputs. push ( new_outputs) ;
1271
+ }
1258
1272
if txn. is_empty ( ) {
1259
1273
txn = self . check_spend_local_transaction ( tx, height) ;
1260
1274
}
@@ -1281,6 +1295,7 @@ impl ChannelMonitor {
1281
1295
}
1282
1296
}
1283
1297
}
1298
+ watch_outputs
1284
1299
}
1285
1300
1286
1301
pub fn would_broadcast_at_height ( & self , height : u32 ) -> bool {
0 commit comments