Skip to content

Commit dfdddbf

Browse files
committed
Send fee estimator through to get_max_htlc_dust_exposure_threshold
1 parent 0baf76f commit dfdddbf

File tree

3 files changed

+84
-54
lines changed

3 files changed

+84
-54
lines changed

lightning/src/ln/channel.rs

Lines changed: 64 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,10 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
10721072
cmp::max(self.config.options.cltv_expiry_delta, MIN_CLTV_EXPIRY_DELTA)
10731073
}
10741074

1075-
pub fn get_max_dust_htlc_exposure_msat(&self) -> u64 {
1075+
pub fn get_max_dust_htlc_exposure_msat<F: Deref>(&self,
1076+
_fee_estimator: &LowerBoundedFeeEstimator<F>) -> u64
1077+
where F::Target: FeeEstimator
1078+
{
10761079
match self.config.options.max_dust_htlc_exposure_msat {
10771080
MaxDustHTLCExposure::FixedLimitMsat(limit) => limit,
10781081
MaxDustHTLCExposure::FeeRateMultiplier(_) => 5_000_000,
@@ -1550,7 +1553,9 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
15501553
/// Doesn't bother handling the
15511554
/// if-we-removed-it-already-but-haven't-fully-resolved-they-can-still-send-an-inbound-HTLC
15521555
/// corner case properly.
1553-
pub fn get_available_balances(&self) -> AvailableBalances {
1556+
pub fn get_available_balances<F: Deref>(&self, fee_estimator: &LowerBoundedFeeEstimator<F>) -> AvailableBalances
1557+
where F::Target: FeeEstimator
1558+
{
15541559
let context = &self;
15551560
// Note that we have to handle overflow due to the above case.
15561561
let inbound_stats = context.get_inbound_pending_htlc_stats(None);
@@ -1632,6 +1637,7 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
16321637
// send above the dust limit (as the router can always overpay to meet the dust limit).
16331638
let mut remaining_msat_below_dust_exposure_limit = None;
16341639
let mut dust_exposure_dust_limit_msat = 0;
1640+
let max_dust_htlc_exposure_msat = context.get_max_dust_htlc_exposure_msat(fee_estimator);
16351641

16361642
let (htlc_success_dust_limit, htlc_timeout_dust_limit) = if context.opt_anchors() {
16371643
(context.counterparty_dust_limit_satoshis, context.holder_dust_limit_satoshis)
@@ -1641,17 +1647,17 @@ impl<Signer: ChannelSigner> ChannelContext<Signer> {
16411647
context.holder_dust_limit_satoshis + dust_buffer_feerate * htlc_timeout_tx_weight(false) / 1000)
16421648
};
16431649
let on_counterparty_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat;
1644-
if on_counterparty_dust_htlc_exposure_msat as i64 + htlc_success_dust_limit as i64 * 1000 - 1 > context.get_max_dust_htlc_exposure_msat() as i64 {
1650+
if on_counterparty_dust_htlc_exposure_msat as i64 + htlc_success_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat as i64 {
16451651
remaining_msat_below_dust_exposure_limit =
1646-
Some(context.get_max_dust_htlc_exposure_msat().saturating_sub(on_counterparty_dust_htlc_exposure_msat));
1652+
Some(max_dust_htlc_exposure_msat.saturating_sub(on_counterparty_dust_htlc_exposure_msat));
16471653
dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_success_dust_limit * 1000);
16481654
}
16491655

16501656
let on_holder_dust_htlc_exposure_msat = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
1651-
if on_holder_dust_htlc_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > context.get_max_dust_htlc_exposure_msat() as i64 {
1657+
if on_holder_dust_htlc_exposure_msat as i64 + htlc_timeout_dust_limit as i64 * 1000 - 1 > max_dust_htlc_exposure_msat as i64 {
16521658
remaining_msat_below_dust_exposure_limit = Some(cmp::min(
16531659
remaining_msat_below_dust_exposure_limit.unwrap_or(u64::max_value()),
1654-
context.get_max_dust_htlc_exposure_msat().saturating_sub(on_holder_dust_htlc_exposure_msat)));
1660+
max_dust_htlc_exposure_msat.saturating_sub(on_holder_dust_htlc_exposure_msat)));
16551661
dust_exposure_dust_limit_msat = cmp::max(dust_exposure_dust_limit_msat, htlc_timeout_dust_limit * 1000);
16561662
}
16571663

@@ -2582,8 +2588,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
25822588
Ok(self.get_announcement_sigs(node_signer, genesis_block_hash, user_config, best_block.height(), logger))
25832589
}
25842590

2585-
pub fn update_add_htlc<F, L: Deref>(&mut self, msg: &msgs::UpdateAddHTLC, mut pending_forward_status: PendingHTLCStatus, create_pending_htlc_status: F, logger: &L) -> Result<(), ChannelError>
2586-
where F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus, L::Target: Logger {
2591+
pub fn update_add_htlc<F, FE: Deref, L: Deref>(&mut self, msg: &msgs::UpdateAddHTLC, mut pending_forward_status: PendingHTLCStatus, create_pending_htlc_status: F, fee_estimator: &LowerBoundedFeeEstimator<FE>, logger: &L) -> Result<(), ChannelError>
2592+
where F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus,
2593+
FE::Target: FeeEstimator, L::Target: Logger {
25872594
// We can't accept HTLCs sent after we've sent a shutdown.
25882595
let local_sent_shutdown = (self.context.channel_state & (ChannelState::ChannelReady as u32 | ChannelState::LocalShutdownSent as u32)) != (ChannelState::ChannelReady as u32);
25892596
if local_sent_shutdown {
@@ -2636,6 +2643,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
26362643
}
26372644
}
26382645

2646+
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
26392647
let (htlc_timeout_dust_limit, htlc_success_dust_limit) = if self.context.opt_anchors() {
26402648
(0, 0)
26412649
} else {
@@ -2646,19 +2654,19 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
26462654
let exposure_dust_limit_timeout_sats = htlc_timeout_dust_limit + self.context.counterparty_dust_limit_satoshis;
26472655
if msg.amount_msat / 1000 < exposure_dust_limit_timeout_sats {
26482656
let on_counterparty_tx_dust_htlc_exposure_msat = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat + msg.amount_msat;
2649-
if on_counterparty_tx_dust_htlc_exposure_msat > self.context.get_max_dust_htlc_exposure_msat() {
2657+
if on_counterparty_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
26502658
log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on counterparty commitment tx",
2651-
on_counterparty_tx_dust_htlc_exposure_msat, self.context.get_max_dust_htlc_exposure_msat());
2659+
on_counterparty_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
26522660
pending_forward_status = create_pending_htlc_status(self, pending_forward_status, 0x1000|7);
26532661
}
26542662
}
26552663

26562664
let exposure_dust_limit_success_sats = htlc_success_dust_limit + self.context.holder_dust_limit_satoshis;
26572665
if msg.amount_msat / 1000 < exposure_dust_limit_success_sats {
26582666
let on_holder_tx_dust_htlc_exposure_msat = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat + msg.amount_msat;
2659-
if on_holder_tx_dust_htlc_exposure_msat > self.context.get_max_dust_htlc_exposure_msat() {
2667+
if on_holder_tx_dust_htlc_exposure_msat > max_dust_htlc_exposure_msat {
26602668
log_info!(logger, "Cannot accept value that would put our exposure to dust HTLCs at {} over the limit {} on holder commitment tx",
2661-
on_holder_tx_dust_htlc_exposure_msat, self.context.get_max_dust_htlc_exposure_msat());
2669+
on_holder_tx_dust_htlc_exposure_msat, max_dust_htlc_exposure_msat);
26622670
pending_forward_status = create_pending_htlc_status(self, pending_forward_status, 0x1000|7);
26632671
}
26642672
}
@@ -3025,16 +3033,18 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
30253033
/// Public version of the below, checking relevant preconditions first.
30263034
/// If we're not in a state where freeing the holding cell makes sense, this is a no-op and
30273035
/// returns `(None, Vec::new())`.
3028-
pub fn maybe_free_holding_cell_htlcs<L: Deref>(&mut self, logger: &L) -> (Option<&ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>) where L::Target: Logger {
3036+
pub fn maybe_free_holding_cell_htlcs<F: Deref, L: Deref>(&mut self, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> (Option<&ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>) where F::Target: FeeEstimator, L::Target: Logger {
30293037
if self.context.channel_state >= ChannelState::ChannelReady as u32 &&
30303038
(self.context.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::PeerDisconnected as u32 | ChannelState::MonitorUpdateInProgress as u32)) == 0 {
3031-
self.free_holding_cell_htlcs(logger)
3039+
self.free_holding_cell_htlcs(fee_estimator, logger)
30323040
} else { (None, Vec::new()) }
30333041
}
30343042

30353043
/// Frees any pending commitment updates in the holding cell, generating the relevant messages
30363044
/// for our counterparty.
3037-
fn free_holding_cell_htlcs<L: Deref>(&mut self, logger: &L) -> (Option<&ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>) where L::Target: Logger {
3045+
fn free_holding_cell_htlcs<F: Deref, L: Deref>(&mut self, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> (Option<&ChannelMonitorUpdate>, Vec<(HTLCSource, PaymentHash)>)
3046+
where F::Target: FeeEstimator, L::Target: Logger
3047+
{
30383048
assert_eq!(self.context.channel_state & ChannelState::MonitorUpdateInProgress as u32, 0);
30393049
if self.context.holding_cell_htlc_updates.len() != 0 || self.context.holding_cell_update_fee.is_some() {
30403050
log_trace!(logger, "Freeing holding cell with {} HTLC updates{} in channel {}", self.context.holding_cell_htlc_updates.len(),
@@ -3063,7 +3073,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
30633073
skimmed_fee_msat, ..
30643074
} => {
30653075
match self.send_htlc(amount_msat, *payment_hash, cltv_expiry, source.clone(),
3066-
onion_routing_packet.clone(), false, skimmed_fee_msat, logger)
3076+
onion_routing_packet.clone(), false, skimmed_fee_msat, fee_estimator, logger)
30673077
{
30683078
Ok(update_add_msg_option) => update_add_htlcs.push(update_add_msg_option.unwrap()),
30693079
Err(e) => {
@@ -3123,7 +3133,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
31233133
return (None, htlcs_to_fail);
31243134
}
31253135
let update_fee = if let Some(feerate) = self.context.holding_cell_update_fee.take() {
3126-
self.send_update_fee(feerate, false, logger)
3136+
self.send_update_fee(feerate, false, fee_estimator, logger)
31273137
} else {
31283138
None
31293139
};
@@ -3150,8 +3160,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
31503160
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
31513161
/// generating an appropriate error *after* the channel state has been updated based on the
31523162
/// revoke_and_ack message.
3153-
pub fn revoke_and_ack<L: Deref>(&mut self, msg: &msgs::RevokeAndACK, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
3154-
where L::Target: Logger,
3163+
pub fn revoke_and_ack<F: Deref, L: Deref>(&mut self, msg: &msgs::RevokeAndACK, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Result<(Vec<(HTLCSource, PaymentHash)>, Option<&ChannelMonitorUpdate>), ChannelError>
3164+
where F::Target: FeeEstimator, L::Target: Logger,
31553165
{
31563166
if (self.context.channel_state & (ChannelState::ChannelReady as u32)) != (ChannelState::ChannelReady as u32) {
31573167
return Err(ChannelError::Close("Got revoke/ACK message when channel was not in an operational state".to_owned()));
@@ -3351,7 +3361,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
33513361
return Ok((Vec::new(), self.push_ret_blockable_mon_update(monitor_update)));
33523362
}
33533363

3354-
match self.free_holding_cell_htlcs(logger) {
3364+
match self.free_holding_cell_htlcs(fee_estimator, logger) {
33553365
(Some(_), htlcs_to_fail) => {
33563366
let mut additional_update = self.context.pending_monitor_updates.pop().unwrap().update;
33573367
// free_holding_cell_htlcs may bump latest_monitor_id multiple times but we want them to be
@@ -3387,8 +3397,11 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
33873397
/// Queues up an outbound update fee by placing it in the holding cell. You should call
33883398
/// [`Self::maybe_free_holding_cell_htlcs`] in order to actually generate and send the
33893399
/// commitment update.
3390-
pub fn queue_update_fee<L: Deref>(&mut self, feerate_per_kw: u32, logger: &L) where L::Target: Logger {
3391-
let msg_opt = self.send_update_fee(feerate_per_kw, true, logger);
3400+
pub fn queue_update_fee<F: Deref, L: Deref>(&mut self, feerate_per_kw: u32,
3401+
fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L)
3402+
where F::Target: FeeEstimator, L::Target: Logger
3403+
{
3404+
let msg_opt = self.send_update_fee(feerate_per_kw, true, fee_estimator, logger);
33923405
assert!(msg_opt.is_none(), "We forced holding cell?");
33933406
}
33943407

@@ -3399,7 +3412,9 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
33993412
///
34003413
/// You MUST call [`Self::send_commitment_no_state_update`] prior to any other calls on this
34013414
/// [`Channel`] if `force_holding_cell` is false.
3402-
fn send_update_fee<L: Deref>(&mut self, feerate_per_kw: u32, mut force_holding_cell: bool, logger: &L) -> Option<msgs::UpdateFee> where L::Target: Logger {
3415+
fn send_update_fee<F: Deref, L: Deref>(&mut self, feerate_per_kw: u32, mut force_holding_cell: bool, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L) -> Option<msgs::UpdateFee>
3416+
where F::Target: FeeEstimator, L::Target: Logger
3417+
{
34033418
if !self.context.is_outbound() {
34043419
panic!("Cannot send fee from inbound channel");
34053420
}
@@ -3426,11 +3441,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
34263441
// Note, we evaluate pending htlc "preemptive" trimmed-to-dust threshold at the proposed `feerate_per_kw`.
34273442
let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
34283443
let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat;
3429-
if holder_tx_dust_exposure > self.context.get_max_dust_htlc_exposure_msat() {
3444+
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
3445+
if holder_tx_dust_exposure > max_dust_htlc_exposure_msat {
34303446
log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw);
34313447
return None;
34323448
}
3433-
if counterparty_tx_dust_exposure > self.context.get_max_dust_htlc_exposure_msat() {
3449+
if counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat {
34343450
log_debug!(logger, "Cannot afford to send new feerate at {} without infringing max dust htlc exposure", feerate_per_kw);
34353451
return None;
34363452
}
@@ -3667,11 +3683,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
36673683
let outbound_stats = self.context.get_outbound_pending_htlc_stats(None);
36683684
let holder_tx_dust_exposure = inbound_stats.on_holder_tx_dust_exposure_msat + outbound_stats.on_holder_tx_dust_exposure_msat;
36693685
let counterparty_tx_dust_exposure = inbound_stats.on_counterparty_tx_dust_exposure_msat + outbound_stats.on_counterparty_tx_dust_exposure_msat;
3670-
if holder_tx_dust_exposure > self.context.get_max_dust_htlc_exposure_msat() {
3686+
let max_dust_htlc_exposure_msat = self.context.get_max_dust_htlc_exposure_msat(fee_estimator);
3687+
if holder_tx_dust_exposure > max_dust_htlc_exposure_msat {
36713688
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our own transactions (totaling {} msat)",
36723689
msg.feerate_per_kw, holder_tx_dust_exposure)));
36733690
}
3674-
if counterparty_tx_dust_exposure > self.context.get_max_dust_htlc_exposure_msat() {
3691+
if counterparty_tx_dust_exposure > max_dust_htlc_exposure_msat {
36753692
return Err(ChannelError::Close(format!("Peer sent update_fee with a feerate ({}) which may over-expose us to dust-in-flight on our counterparty's transactions (totaling {} msat)",
36763693
msg.feerate_per_kw, counterparty_tx_dust_exposure)));
36773694
}
@@ -5054,13 +5071,16 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
50545071
/// commitment update.
50555072
///
50565073
/// `Err`s will only be [`ChannelError::Ignore`].
5057-
pub fn queue_add_htlc<L: Deref>(
5074+
pub fn queue_add_htlc<F: Deref, L: Deref>(
50585075
&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource,
5059-
onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option<u64>, logger: &L
5060-
) -> Result<(), ChannelError> where L::Target: Logger {
5076+
onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option<u64>,
5077+
fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L
5078+
) -> Result<(), ChannelError>
5079+
where F::Target: FeeEstimator, L::Target: Logger
5080+
{
50615081
self
50625082
.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, true,
5063-
skimmed_fee_msat, logger)
5083+
skimmed_fee_msat, fee_estimator, logger)
50645084
.map(|msg_opt| assert!(msg_opt.is_none(), "We forced holding cell?"))
50655085
.map_err(|err| {
50665086
if let ChannelError::Ignore(_) = err { /* fine */ }
@@ -5085,11 +5105,13 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
50855105
/// on this [`Channel`] if `force_holding_cell` is false.
50865106
///
50875107
/// `Err`s will only be [`ChannelError::Ignore`].
5088-
fn send_htlc<L: Deref>(
5108+
fn send_htlc<F: Deref, L: Deref>(
50895109
&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource,
50905110
onion_routing_packet: msgs::OnionPacket, mut force_holding_cell: bool,
5091-
skimmed_fee_msat: Option<u64>, logger: &L
5092-
) -> Result<Option<msgs::UpdateAddHTLC>, ChannelError> where L::Target: Logger {
5111+
skimmed_fee_msat: Option<u64>, fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L
5112+
) -> Result<Option<msgs::UpdateAddHTLC>, ChannelError>
5113+
where F::Target: FeeEstimator, L::Target: Logger
5114+
{
50935115
if (self.context.channel_state & (ChannelState::ChannelReady as u32 | BOTH_SIDES_SHUTDOWN_MASK)) != (ChannelState::ChannelReady as u32) {
50945116
return Err(ChannelError::Ignore("Cannot send HTLC until channel is fully established and we haven't started shutting down".to_owned()));
50955117
}
@@ -5102,7 +5124,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
51025124
return Err(ChannelError::Ignore("Cannot send 0-msat HTLC".to_owned()));
51035125
}
51045126

5105-
let available_balances = self.context.get_available_balances();
5127+
let available_balances = self.context.get_available_balances(fee_estimator);
51065128
if amount_msat < available_balances.next_outbound_htlc_minimum_msat {
51075129
return Err(ChannelError::Ignore(format!("Cannot send less than our next-HTLC minimum - {} msat",
51085130
available_balances.next_outbound_htlc_minimum_msat)));
@@ -5302,12 +5324,15 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
53025324
///
53035325
/// Shorthand for calling [`Self::send_htlc`] followed by a commitment update, see docs on
53045326
/// [`Self::send_htlc`] and [`Self::build_commitment_no_state_update`] for more info.
5305-
pub fn send_htlc_and_commit<L: Deref>(
5327+
pub fn send_htlc_and_commit<F: Deref, L: Deref>(
53065328
&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource,
5307-
onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option<u64>, logger: &L
5308-
) -> Result<Option<&ChannelMonitorUpdate>, ChannelError> where L::Target: Logger {
5329+
onion_routing_packet: msgs::OnionPacket, skimmed_fee_msat: Option<u64>,
5330+
fee_estimator: &LowerBoundedFeeEstimator<F>, logger: &L
5331+
) -> Result<Option<&ChannelMonitorUpdate>, ChannelError>
5332+
where F::Target: FeeEstimator, L::Target: Logger
5333+
{
53095334
let send_res = self.send_htlc(amount_msat, payment_hash, cltv_expiry, source,
5310-
onion_routing_packet, false, skimmed_fee_msat, logger);
5335+
onion_routing_packet, false, skimmed_fee_msat, fee_estimator, logger);
53115336
if let Err(e) = &send_res { if let ChannelError::Ignore(_) = e {} else { debug_assert!(false, "Sending cannot trigger channel failure"); } }
53125337
match send_res? {
53135338
Some(_) => {

0 commit comments

Comments
 (0)