Skip to content

Commit 98134c8

Browse files
committed
Gracefully handle fee-larger-than-claimed-value in ChannelMonitor
This resulted in a full_stack_target failure as we overflow during subtraction otherwise. Instead, we try lower and lower fee estimator confirmation targets until we find one low enough, or discard the transaction. We should be able to handle this much cleaner, but for now this at least gets the fuzzer working again.
1 parent 02feaeb commit 98134c8

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)