Skip to content

Commit f0e1aff

Browse files
committed
wip: witness weight estimates
1 parent 67031f8 commit f0e1aff

File tree

1 file changed

+27
-6
lines changed

1 file changed

+27
-6
lines changed

lightning/src/ln/interactivetxs.rs

+27-6
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use crate::events::bump_transaction::{BASE_INPUT_WEIGHT, EMPTY_SCRIPT_SIG_WEIGHT
2323
use crate::ln::channel::TOTAL_BITCOIN_SUPPLY_SATOSHIS;
2424
use crate::ln::msgs::SerialId;
2525
use crate::ln::{msgs, ChannelId};
26-
use crate::sign::EntropySource;
26+
use crate::sign::{EntropySource, P2WPKH_WITNESS_WEIGHT};
2727
use crate::util::ser::TransactionU16LenLimited;
2828

2929
/// The number of received `tx_add_input` messages during a negotiation at which point the
@@ -364,9 +364,6 @@ impl NegotiationContext {
364364
return Err(AbortReason::ExceededNumberOfInputsOrOutputs);
365365
}
366366

367-
// TODO: How do we enforce their fees cover the witness without knowing its expected length?
368-
const INPUT_WEIGHT: u64 = BASE_INPUT_WEIGHT + EMPTY_SCRIPT_SIG_WEIGHT;
369-
370367
// - the peer's paid feerate does not meet or exceed the agreed feerate (based on the minimum fee).
371368
let mut counterparty_weight_contributed: u64 = self
372369
.counterparty_outputs_contributed()
@@ -375,8 +372,32 @@ impl NegotiationContext {
375372
* WITNESS_SCALE_FACTOR as u64
376373
})
377374
.sum();
378-
counterparty_weight_contributed +=
379-
self.counterparty_inputs_contributed().count() as u64 * INPUT_WEIGHT;
375+
// We don't know the counterparty's witnesses ahead of time obviously, so we need to have some
376+
// estimates for their weights based on script type. We make some reasonably assumptions here.
377+
let mut total_inputs_weight: u64 = 0;
378+
for TxInputWithPrevOutput { prev_output, .. } in self.counterparty_inputs_contributed() {
379+
total_inputs_weight = total_inputs_weight
380+
.saturating_add(BASE_INPUT_WEIGHT)
381+
.saturating_add(if prev_output.script_pubkey.is_v0_p2wpkh() {
382+
// The weight for a P2WPKH spend is fixed.
383+
EMPTY_SCRIPT_SIG_WEIGHT + P2WPKH_WITNESS_WEIGHT
384+
} else if prev_output.script_pubkey.is_v0_p2wsh() {
385+
// We cover a 2-of-2 multisig spend case as a minimum estimated weight. We assume signature
386+
// grinding (71 byte signatures) here as we do add fee margin of error anyway.
387+
EMPTY_SCRIPT_SIG_WEIGHT + 1 /* witness items */ + 1 /* multisig dummy element */ + 1 /* 1st sig len */
388+
+ 71 /* 1st sig */ + 1 /* 2nd sig len */ + 71 /* 2nd sig */ + 1 /* witness script len */
389+
+ 1 /* signature count */ + 1 /* 1st pubkey len */ + 33 /* 1st pubkey */ + 1 /* 2nd pubkey len */
390+
+ 33 /* 2nd pubkey */ + 1 /* pubkey count */ + 1 /* OP_CHECKMULTISIG */
391+
} else if prev_output.script_pubkey.is_v1_p2tr() {
392+
// We cover the key path spend case as a minimum estimated weight.
393+
EMPTY_SCRIPT_SIG_WEIGHT + 1 /* witness items */ + 1 /* schnorr sig len */ + 64 /* schnorr sig */
394+
} else {
395+
// The case for witness programs with versions greater than V1. At this stage they're anyone-can-spend.
396+
EMPTY_SCRIPT_SIG_WEIGHT
397+
});
398+
}
399+
counterparty_weight_contributed =
400+
counterparty_weight_contributed.saturating_add(total_inputs_weight);
380401
let counterparty_fees_contributed =
381402
counterparty_inputs_value.saturating_sub(counterparty_outputs_value);
382403
let mut required_counterparty_contribution_fee =

0 commit comments

Comments
 (0)