@@ -34,7 +34,7 @@ use ln::chan_utils;
34
34
use ln:: chan_utils:: HTLCOutputInCommitment ;
35
35
use ln:: channelmanager:: { HTLCSource , PaymentPreimage , PaymentHash } ;
36
36
use ln:: channel:: { ACCEPTED_HTLC_SCRIPT_WEIGHT , OFFERED_HTLC_SCRIPT_WEIGHT } ;
37
- use chain:: chaininterface:: { ChainListener , ChainWatchInterface , BroadcasterInterface } ;
37
+ use chain:: chaininterface:: { ChainListener , ChainWatchInterface , BroadcasterInterface , FeeEstimator , ConfirmationTarget } ;
38
38
use chain:: transaction:: OutPoint ;
39
39
use chain:: keysinterface:: SpendableOutputDescriptor ;
40
40
use util:: logger:: Logger ;
@@ -143,6 +143,7 @@ pub struct SimpleManyChannelMonitor<Key> {
143
143
pending_events : Mutex < Vec < events:: Event > > ,
144
144
pending_htlc_updated : Mutex < HashMap < PaymentHash , Vec < ( HTLCSource , Option < PaymentPreimage > ) > > > ,
145
145
logger : Arc < Logger > ,
146
+ fee_estimator : Arc < FeeEstimator >
146
147
}
147
148
148
149
impl < Key : Send + cmp:: Eq + hash:: Hash > ChainListener for SimpleManyChannelMonitor < Key > {
@@ -153,7 +154,7 @@ impl<Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonit
153
154
{
154
155
let mut monitors = self . monitors . lock ( ) . unwrap ( ) ;
155
156
for monitor in monitors. values_mut ( ) {
156
- let ( txn_outputs, spendable_outputs, mut htlc_updated) = monitor. block_connected ( txn_matched, height, & block_hash, & * self . broadcaster ) ;
157
+ let ( txn_outputs, spendable_outputs, mut htlc_updated) = monitor. block_connected ( txn_matched, height, & block_hash, & * self . broadcaster , & * self . fee_estimator ) ;
157
158
if spendable_outputs. len ( ) > 0 {
158
159
new_events. push ( events:: Event :: SpendableOutputs {
159
160
outputs : spendable_outputs,
@@ -210,14 +211,15 @@ impl<Key : Send + cmp::Eq + hash::Hash> ChainListener for SimpleManyChannelMonit
210
211
impl < Key : Send + cmp:: Eq + hash:: Hash + ' static > SimpleManyChannelMonitor < Key > {
211
212
/// Creates a new object which can be used to monitor several channels given the chain
212
213
/// interface with which to register to receive notifications.
213
- pub fn new ( chain_monitor : Arc < ChainWatchInterface > , broadcaster : Arc < BroadcasterInterface > , logger : Arc < Logger > ) -> Arc < SimpleManyChannelMonitor < Key > > {
214
+ pub fn new ( chain_monitor : Arc < ChainWatchInterface > , broadcaster : Arc < BroadcasterInterface > , logger : Arc < Logger > , feeest : Arc < FeeEstimator > ) -> Arc < SimpleManyChannelMonitor < Key > > {
214
215
let res = Arc :: new ( SimpleManyChannelMonitor {
215
216
monitors : Mutex :: new ( HashMap :: new ( ) ) ,
216
217
chain_monitor,
217
218
broadcaster,
218
219
pending_events : Mutex :: new ( Vec :: new ( ) ) ,
219
220
pending_htlc_updated : Mutex :: new ( HashMap :: new ( ) ) ,
220
221
logger,
222
+ fee_estimator : feeest,
221
223
} ) ;
222
224
let weak_res = Arc :: downgrade ( & res) ;
223
225
res. chain_monitor . register_listener ( weak_res) ;
@@ -306,6 +308,11 @@ pub(crate) const HTLC_FAIL_TIMEOUT_BLOCKS: u32 = 3;
306
308
/// and then getting a reorg resulting in us losing money.
307
309
//TODO: We currently don't actually use this...we should
308
310
pub ( crate ) const HTLC_FAIL_ANTI_REORG_DELAY : u32 = 6 ;
311
+ /// A claim tx is either a justice tx on remote revoked outputs or a HTLC-solving tx on remote valid HTLC outputs.
312
+ /// Its construction is free to us, i.e we may choose to batch in one single claim tx all outpoints for which
313
+ /// we have solving witness programs modulo HTLC expiration requirements.
314
+ /// Base weight is at least : 4 (version) + 2 (segwit flag) + 1 (out-counter) + 8 (single-ouput value) + 4 (locktime)
315
+ const CLAIM_TX_BASE_WEIGHT : u64 = 4 + 2 + 1 + 8 + 4 ;
309
316
310
317
#[ derive( Clone , PartialEq ) ]
311
318
enum Storage {
@@ -340,6 +347,14 @@ struct LocalSignedTx {
340
347
htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < ( Signature , Signature ) > , Option < HTLCSource > ) > ,
341
348
}
342
349
350
+ enum InputDescriptors {
351
+ RevokedOfferedHTLC ,
352
+ RevokedReceivedHTLC ,
353
+ OfferedHTLC ,
354
+ ReceivedHTLC ,
355
+ RevokedOutput , // either a revoked to_local output on commitment tx, a revoked HTLC-Timeout output or a revoked HTLC-Success output
356
+ }
357
+
343
358
const SERIALIZATION_VERSION : u8 = 1 ;
344
359
const MIN_SERIALIZATION_VERSION : u8 = 1 ;
345
360
@@ -475,6 +490,32 @@ impl ChannelMonitor {
475
490
}
476
491
}
477
492
493
+ fn get_claim_tx_weight ( inputs : Vec < InputDescriptors > , output_scriptpubkey : & Script ) -> u64 {
494
+ let mut tx_weight = CLAIM_TX_BASE_WEIGHT ;
495
+ tx_weight += if inputs. len ( ) > 255 { 2 } else { 1 } ;
496
+ for inp in inputs {
497
+ tx_weight += match inp {
498
+ InputDescriptors :: RevokedOfferedHTLC => {
499
+ 41 + 1 + 1 + 73 + 1 + 33 + 1 + 133
500
+ } ,
501
+ InputDescriptors :: RevokedReceivedHTLC => {
502
+ 41 + 1 + 1 + 73 + 1 + 33 + 1 + 139
503
+ } ,
504
+ InputDescriptors :: OfferedHTLC => {
505
+ 41 + 1 + 1 + 73 + 1 + 32 + 1 + 133
506
+ } ,
507
+ InputDescriptors :: ReceivedHTLC => {
508
+ 41 + 1 + 1 + 73 + 1 + 1 + 139
509
+ } ,
510
+ InputDescriptors :: RevokedOutput => {
511
+ 41 + 1 + 1 + 73 + 1 + 1 + 1 + 82
512
+ } ,
513
+ } ;
514
+ }
515
+ tx_weight += output_scriptpubkey. len ( ) as u64 ;
516
+ tx_weight
517
+ }
518
+
478
519
#[ inline]
479
520
fn place_secret ( idx : u64 ) -> u8 {
480
521
for i in 0 ..48 {
@@ -1019,7 +1060,7 @@ impl ChannelMonitor {
1019
1060
/// HTLC-Success/HTLC-Timeout transactions.
1020
1061
/// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
1021
1062
/// revoked remote commitment tx
1022
- fn check_spend_remote_transaction ( & mut self , tx : & Transaction , height : u32 ) -> ( Vec < Transaction > , ( Sha256dHash , Vec < TxOut > ) , Vec < SpendableOutputDescriptor > , Vec < ( HTLCSource , Option < PaymentPreimage > , PaymentHash ) > ) {
1063
+ fn check_spend_remote_transaction ( & mut self , tx : & Transaction , height : u32 , fee_estimator : & FeeEstimator ) -> ( Vec < Transaction > , ( Sha256dHash , Vec < TxOut > ) , Vec < SpendableOutputDescriptor > , Vec < ( HTLCSource , Option < PaymentPreimage > , PaymentHash ) > ) {
1023
1064
// Most secp and related errors trying to create keys means we have no hope of constructing
1024
1065
// a spend transaction...so we return no transactions to broadcast
1025
1066
let mut txn_to_broadcast = Vec :: new ( ) ;
@@ -1077,6 +1118,7 @@ impl ChannelMonitor {
1077
1118
let mut values = Vec :: new ( ) ;
1078
1119
let mut inputs = Vec :: new ( ) ;
1079
1120
let mut htlc_idxs = Vec :: new ( ) ;
1121
+ let mut input_descriptors = Vec :: new ( ) ;
1080
1122
1081
1123
for ( idx, outp) in tx. output . iter ( ) . enumerate ( ) {
1082
1124
if outp. script_pubkey == revokeable_p2wsh {
@@ -1092,6 +1134,7 @@ impl ChannelMonitor {
1092
1134
htlc_idxs. push ( None ) ;
1093
1135
values. push ( outp. value ) ;
1094
1136
total_value += outp. value ;
1137
+ input_descriptors. push ( InputDescriptors :: RevokedOutput ) ;
1095
1138
} else if Some ( & outp. script_pubkey ) == local_payment_p2wpkh. as_ref ( ) {
1096
1139
spendable_outputs. push ( SpendableOutputDescriptor :: DynamicOutputP2WPKH {
1097
1140
outpoint : BitcoinOutPoint { txid : commitment_txid, vout : idx as u32 } ,
@@ -1155,6 +1198,7 @@ impl ChannelMonitor {
1155
1198
htlc_idxs. push ( Some ( idx) ) ;
1156
1199
values. push ( tx. output [ transaction_output_index as usize ] . value ) ;
1157
1200
total_value += htlc. amount_msat / 1000 ;
1201
+ input_descriptors. push ( if htlc. offered { InputDescriptors :: RevokedOfferedHTLC } else { InputDescriptors :: RevokedReceivedHTLC } ) ;
1158
1202
} else {
1159
1203
let mut single_htlc_tx = Transaction {
1160
1204
version : 2 ,
@@ -1165,6 +1209,7 @@ impl ChannelMonitor {
1165
1209
value: htlc. amount_msat / 1000 , //TODO: - fee
1166
1210
} ) ,
1167
1211
} ;
1212
+ single_htlc_tx. output [ 0 ] . value -= fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: HighPriority ) * Self :: get_claim_tx_weight ( vec ! [ if htlc. offered { InputDescriptors :: RevokedOfferedHTLC } else { InputDescriptors :: RevokedReceivedHTLC } ] , & single_htlc_tx. output [ 0 ] . script_pubkey ) / 1000 ;
1168
1213
let sighash_parts = bip143:: SighashComponents :: new ( & single_htlc_tx) ;
1169
1214
sign_input ! ( sighash_parts, single_htlc_tx. input[ 0 ] , Some ( idx) , htlc. amount_msat / 1000 ) ;
1170
1215
txn_to_broadcast. push ( single_htlc_tx) ;
@@ -1208,7 +1253,7 @@ impl ChannelMonitor {
1208
1253
1209
1254
let outputs = vec ! ( TxOut {
1210
1255
script_pubkey: self . destination_script. clone( ) ,
1211
- value: total_value, //TODO: - fee
1256
+ value: total_value - fee_estimator . get_est_sat_per_1000_weight ( ConfirmationTarget :: HighPriority ) * Self :: get_claim_tx_weight ( input_descriptors , & self . destination_script ) / 1000 ,
1212
1257
} ) ;
1213
1258
let mut spend_tx = Transaction {
1214
1259
version : 2 ,
@@ -1324,6 +1369,7 @@ impl ChannelMonitor {
1324
1369
let mut total_value = 0 ;
1325
1370
let mut values = Vec :: new ( ) ;
1326
1371
let mut inputs = Vec :: new ( ) ;
1372
+ let mut input_descriptors = Vec :: new ( ) ;
1327
1373
1328
1374
macro_rules! sign_input {
1329
1375
( $sighash_parts: expr, $input: expr, $amount: expr, $preimage: expr) => {
@@ -1370,16 +1416,18 @@ impl ChannelMonitor {
1370
1416
inputs. push ( input) ;
1371
1417
values. push ( ( tx. output [ transaction_output_index as usize ] . value , payment_preimage) ) ;
1372
1418
total_value += htlc. amount_msat / 1000 ;
1419
+ input_descriptors. push ( if htlc. offered { InputDescriptors :: OfferedHTLC } else { InputDescriptors :: ReceivedHTLC } ) ;
1373
1420
} else {
1374
1421
let mut single_htlc_tx = Transaction {
1375
1422
version : 2 ,
1376
1423
lock_time : 0 ,
1377
1424
input : vec ! [ input] ,
1378
1425
output : vec ! ( TxOut {
1379
1426
script_pubkey: self . destination_script. clone( ) ,
1380
- value: htlc. amount_msat / 1000 , //TODO: - fee
1427
+ value: htlc. amount_msat / 1000 ,
1381
1428
} ) ,
1382
1429
} ;
1430
+ single_htlc_tx. output [ 0 ] . value -= fee_estimator. get_est_sat_per_1000_weight ( ConfirmationTarget :: HighPriority ) * Self :: get_claim_tx_weight ( vec ! [ if htlc. offered { InputDescriptors :: OfferedHTLC } else { InputDescriptors :: ReceivedHTLC } ] , & single_htlc_tx. output [ 0 ] . script_pubkey ) / 1000 ;
1383
1431
let sighash_parts = bip143:: SighashComponents :: new ( & single_htlc_tx) ;
1384
1432
sign_input ! ( sighash_parts, single_htlc_tx. input[ 0 ] , htlc. amount_msat / 1000 , payment_preimage. 0 . to_vec( ) ) ;
1385
1433
spendable_outputs. push ( SpendableOutputDescriptor :: StaticOutput {
@@ -1421,7 +1469,7 @@ impl ChannelMonitor {
1421
1469
1422
1470
let outputs = vec ! ( TxOut {
1423
1471
script_pubkey: self . destination_script. clone( ) ,
1424
- value: total_value, //TODO: - fee
1472
+ value: total_value - fee_estimator . get_est_sat_per_1000_weight ( ConfirmationTarget :: HighPriority ) * Self :: get_claim_tx_weight ( input_descriptors , & self . destination_script ) / 1000 ,
1425
1473
} ) ;
1426
1474
let mut spend_tx = Transaction {
1427
1475
version : 2 ,
@@ -1698,7 +1746,7 @@ impl ChannelMonitor {
1698
1746
}
1699
1747
}
1700
1748
1701
- fn block_connected ( & mut self , txn_matched : & [ & Transaction ] , height : u32 , block_hash : & Sha256dHash , broadcaster : & BroadcasterInterface ) -> ( Vec < ( Sha256dHash , Vec < TxOut > ) > , Vec < SpendableOutputDescriptor > , Vec < ( HTLCSource , Option < PaymentPreimage > , PaymentHash ) > ) {
1749
+ fn block_connected ( & mut self , txn_matched : & [ & Transaction ] , height : u32 , block_hash : & Sha256dHash , broadcaster : & BroadcasterInterface , fee_estimator : & FeeEstimator ) -> ( Vec < ( Sha256dHash , Vec < TxOut > ) > , Vec < SpendableOutputDescriptor > , Vec < ( HTLCSource , Option < PaymentPreimage > , PaymentHash ) > ) {
1702
1750
let mut watch_outputs = Vec :: new ( ) ;
1703
1751
let mut spendable_outputs = Vec :: new ( ) ;
1704
1752
let mut htlc_updated = Vec :: new ( ) ;
@@ -1719,7 +1767,7 @@ impl ChannelMonitor {
1719
1767
}
1720
1768
} ;
1721
1769
if funding_txo. is_none ( ) || ( prevout. txid == funding_txo. as_ref ( ) . unwrap ( ) . 0 . txid && prevout. vout == funding_txo. as_ref ( ) . unwrap ( ) . 0 . index as u32 ) {
1722
- let ( remote_txn, new_outputs, mut spendable_output, mut updated) = self . check_spend_remote_transaction ( tx, height) ;
1770
+ let ( remote_txn, new_outputs, mut spendable_output, mut updated) = self . check_spend_remote_transaction ( tx, height, fee_estimator ) ;
1723
1771
txn = remote_txn;
1724
1772
spendable_outputs. append ( & mut spendable_output) ;
1725
1773
if !new_outputs. 1 . is_empty ( ) {
0 commit comments