Skip to content

Commit a02d70d

Browse files
authored
Merge pull request #341 from TheBlueMatt/2019-06-fuzz-crash-fee-sub
Gracefully handle fee-larger-than-claimed-value in ChannelMonitor
2 parents 02feaeb + 98134c8 commit a02d70d

File tree

1 file changed

+58
-17
lines changed

1 file changed

+58
-17
lines changed

src/ln/channelmonitor.rs

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,38 @@ pub struct ChannelMonitor {
411411
logger: Arc<Logger>,
412412
}
413413

414+
macro_rules! subtract_high_prio_fee {
415+
($self: ident, $fee_estimator: expr, $value: expr, $predicted_weight: expr, $spent_txid: expr) => {
416+
{
417+
let mut fee = $fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * $predicted_weight / 1000;
418+
if $value <= fee {
419+
fee = $fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal) * $predicted_weight / 1000;
420+
if $value <= fee {
421+
fee = $fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Background) * $predicted_weight / 1000;
422+
if $value <= fee {
423+
log_error!($self, "Failed to generate an on-chain punishment tx spending {} as even low priority fee ({} sat) was more than the entire claim balance ({} sat)",
424+
$spent_txid, fee, $value);
425+
false
426+
} else {
427+
log_warn!($self, "Used low priority fee for on-chain punishment tx spending {} as high priority fee was more than the entire claim balance ({} sat)",
428+
$spent_txid, $value);
429+
$value -= fee;
430+
true
431+
}
432+
} else {
433+
log_warn!($self, "Used medium priority fee for on-chain punishment tx spending {} as high priority fee was more than the entire claim balance ({} sat)",
434+
$spent_txid, $value);
435+
$value -= fee;
436+
true
437+
}
438+
} else {
439+
$value -= fee;
440+
true
441+
}
442+
}
443+
}
444+
}
445+
414446
#[cfg(any(test, feature = "fuzztarget"))]
415447
/// Used only in testing and fuzztarget to check serialization roundtrips don't change the
416448
/// underlying object
@@ -1200,11 +1232,12 @@ impl ChannelMonitor {
12001232
}),
12011233
};
12021234
let predicted_weight = single_htlc_tx.get_weight() + Self::get_witnesses_weight(&[if htlc.offered { InputDescriptors::RevokedOfferedHTLC } else { InputDescriptors::RevokedReceivedHTLC }]);
1203-
single_htlc_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
1204-
let sighash_parts = bip143::SighashComponents::new(&single_htlc_tx);
1205-
sign_input!(sighash_parts, single_htlc_tx.input[0], Some(idx), htlc.amount_msat / 1000);
1206-
assert!(predicted_weight >= single_htlc_tx.get_weight());
1207-
txn_to_broadcast.push(single_htlc_tx);
1235+
if subtract_high_prio_fee!(self, fee_estimator, single_htlc_tx.output[0].value, predicted_weight, tx.txid()) {
1236+
let sighash_parts = bip143::SighashComponents::new(&single_htlc_tx);
1237+
sign_input!(sighash_parts, single_htlc_tx.input[0], Some(idx), htlc.amount_msat / 1000);
1238+
assert!(predicted_weight >= single_htlc_tx.get_weight());
1239+
txn_to_broadcast.push(single_htlc_tx);
1240+
}
12081241
}
12091242
}
12101243
}
@@ -1254,7 +1287,10 @@ impl ChannelMonitor {
12541287
output: outputs,
12551288
};
12561289
let predicted_weight = spend_tx.get_weight() + Self::get_witnesses_weight(&input_descriptors[..]);
1257-
spend_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
1290+
1291+
if !subtract_high_prio_fee!(self, fee_estimator, spend_tx.output[0].value, predicted_weight, tx.txid()) {
1292+
return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated);
1293+
}
12581294

12591295
let mut values_drain = values.drain(..);
12601296
let sighash_parts = bip143::SighashComponents::new(&spend_tx);
@@ -1423,15 +1459,16 @@ impl ChannelMonitor {
14231459
}),
14241460
};
14251461
let predicted_weight = single_htlc_tx.get_weight() + Self::get_witnesses_weight(&[if htlc.offered { InputDescriptors::OfferedHTLC } else { InputDescriptors::ReceivedHTLC }]);
1426-
single_htlc_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
1427-
let sighash_parts = bip143::SighashComponents::new(&single_htlc_tx);
1428-
sign_input!(sighash_parts, single_htlc_tx.input[0], htlc.amount_msat / 1000, payment_preimage.0.to_vec());
1429-
assert!(predicted_weight >= single_htlc_tx.get_weight());
1430-
spendable_outputs.push(SpendableOutputDescriptor::StaticOutput {
1431-
outpoint: BitcoinOutPoint { txid: single_htlc_tx.txid(), vout: 0 },
1432-
output: single_htlc_tx.output[0].clone(),
1433-
});
1434-
txn_to_broadcast.push(single_htlc_tx);
1462+
if subtract_high_prio_fee!(self, fee_estimator, single_htlc_tx.output[0].value, predicted_weight, tx.txid()) {
1463+
let sighash_parts = bip143::SighashComponents::new(&single_htlc_tx);
1464+
sign_input!(sighash_parts, single_htlc_tx.input[0], htlc.amount_msat / 1000, payment_preimage.0.to_vec());
1465+
assert!(predicted_weight >= single_htlc_tx.get_weight());
1466+
spendable_outputs.push(SpendableOutputDescriptor::StaticOutput {
1467+
outpoint: BitcoinOutPoint { txid: single_htlc_tx.txid(), vout: 0 },
1468+
output: single_htlc_tx.output[0].clone(),
1469+
});
1470+
txn_to_broadcast.push(single_htlc_tx);
1471+
}
14351472
}
14361473
}
14371474
if !htlc.offered {
@@ -1475,7 +1512,9 @@ impl ChannelMonitor {
14751512
output: outputs,
14761513
};
14771514
let predicted_weight = spend_tx.get_weight() + Self::get_witnesses_weight(&input_descriptors[..]);
1478-
spend_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
1515+
if !subtract_high_prio_fee!(self, fee_estimator, spend_tx.output[0].value, predicted_weight, tx.txid()) {
1516+
return (txn_to_broadcast, (commitment_txid, watch_outputs), spendable_outputs, htlc_updated);
1517+
}
14791518

14801519
let mut values_drain = values.drain(..);
14811520
let sighash_parts = bip143::SighashComponents::new(&spend_tx);
@@ -1561,7 +1600,9 @@ impl ChannelMonitor {
15611600
output: outputs,
15621601
};
15631602
let predicted_weight = spend_tx.get_weight() + Self::get_witnesses_weight(&[InputDescriptors::RevokedOutput]);
1564-
spend_tx.output[0].value -= fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::HighPriority) * predicted_weight / 1000;
1603+
if !subtract_high_prio_fee!(self, fee_estimator, spend_tx.output[0].value, predicted_weight, tx.txid()) {
1604+
return (None, None);
1605+
}
15651606

15661607
let sighash_parts = bip143::SighashComponents::new(&spend_tx);
15671608

0 commit comments

Comments
 (0)