Skip to content

Commit 380b871

Browse files
committed
Add holder commitment point to channel and unfunded context
We are choosing to move the `HolderCommitmentPoint` (the struct that tracks commitment points retrieved from the signer + the commitment number) to handle channel establishment, where we have no commitment point at all. Previously we introduced this struct to track when we were pending a commitment point (because of an async signer) during normal channel operation, which assumed we always had a commitment point to start out with. Intiially we tried to add an `Uninitialized` variant that held no points, but that meant that we needed to handle that case everywhere which left a bunch of scary/unnecessary unwraps/expects. Instead, we just hold an optional `HolderCommitmentPoint` struct on our unfunded channels, and a non-optional `HolderCommitmentPoint` for funded channels. This commit starts that transition. A following commit will remove the holder commitment point from the current `ChannelContext`. This also makes small fixups to the comments on the HolderCommitmentPoint variants.
1 parent 1a8bf62 commit 380b871

File tree

1 file changed

+116
-81
lines changed

1 file changed

+116
-81
lines changed

lightning/src/ln/channel.rs

Lines changed: 116 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -954,29 +954,27 @@ pub(crate) struct ShutdownResult {
954954
/// commitment points from our signer.
955955
#[derive(Debug, Copy, Clone)]
956956
enum HolderCommitmentPoint {
957-
// TODO: add a variant for before our first commitment point is retrieved
958957
/// We've advanced our commitment number and are waiting on the next commitment point.
959-
/// Until the `get_per_commitment_point` signer method becomes async, this variant
960-
/// will not be used.
958+
///
959+
/// We should retry advancing to `Available` via `try_resolve_pending` once our
960+
/// signer is ready to provide the next commitment point.
961961
PendingNext { transaction_number: u64, current: PublicKey },
962-
/// Our current commitment point is ready, we've cached our next point,
963-
/// and we are not pending a new one.
962+
/// Our current commitment point is ready and we've cached our next point.
964963
Available { transaction_number: u64, current: PublicKey, next: PublicKey },
965964
}
966965

967966
impl HolderCommitmentPoint {
968-
pub fn new<SP: Deref>(signer: &ChannelSignerType<SP>, secp_ctx: &Secp256k1<secp256k1::All>) -> Self
967+
pub fn new<SP: Deref>(signer: &ChannelSignerType<SP>, secp_ctx: &Secp256k1<secp256k1::All>) -> Option<Self>
969968
where SP::Target: SignerProvider
970969
{
971-
HolderCommitmentPoint::Available {
972-
transaction_number: INITIAL_COMMITMENT_NUMBER,
973-
// TODO(async_signing): remove this expect with the Uninitialized variant
974-
current: signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER, secp_ctx)
975-
.expect("Signer must be able to provide initial commitment point"),
976-
// TODO(async_signing): remove this expect with the Uninitialized variant
977-
next: signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, secp_ctx)
978-
.expect("Signer must be able to provide second commitment point"),
979-
}
970+
let current = signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER, secp_ctx).ok()?;
971+
let next = signer.as_ref().get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, secp_ctx).ok();
972+
let point = if let Some(next) = next {
973+
HolderCommitmentPoint::Available { transaction_number: INITIAL_COMMITMENT_NUMBER, current, next }
974+
} else {
975+
HolderCommitmentPoint::PendingNext { transaction_number: INITIAL_COMMITMENT_NUMBER, current }
976+
};
977+
Some(point)
980978
}
981979

982980
pub fn is_available(&self) -> bool {
@@ -1169,6 +1167,8 @@ pub(super) struct UnfundedChannelContext {
11691167
/// This is so that we don't keep channels around that haven't progressed to a funded state
11701168
/// in a timely manner.
11711169
unfunded_channel_age_ticks: usize,
1170+
/// Tracks the commitment number and commitment point before the channel is funded.
1171+
holder_commitment_point: Option<HolderCommitmentPoint>,
11721172
}
11731173

11741174
impl UnfundedChannelContext {
@@ -1180,6 +1180,11 @@ impl UnfundedChannelContext {
11801180
self.unfunded_channel_age_ticks += 1;
11811181
self.unfunded_channel_age_ticks >= UNFUNDED_CHANNEL_AGE_LIMIT_TICKS
11821182
}
1183+
1184+
fn transaction_number(&self) -> u64 {
1185+
self.holder_commitment_point.as_ref().map(|point| point.transaction_number())
1186+
.unwrap_or(INITIAL_COMMITMENT_NUMBER)
1187+
}
11831188
}
11841189

11851190
/// Contains everything about the channel including state, and various flags.
@@ -2058,7 +2063,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
20582063
let value_to_self_msat = our_funding_satoshis * 1000 + msg_push_msat;
20592064

20602065
let holder_signer = ChannelSignerType::Ecdsa(holder_signer);
2061-
let holder_commitment_point = HolderCommitmentPoint::new(&holder_signer, &secp_ctx);
2066+
// Unwrap here since it gets removed in the next commit
2067+
let holder_commitment_point = HolderCommitmentPoint::new(&holder_signer, &secp_ctx).unwrap();
20622068

20632069
// TODO(dual_funding): Checks for `funding_feerate_sat_per_1000_weight`?
20642070

@@ -2297,7 +2303,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
22972303
let temporary_channel_id = temporary_channel_id.unwrap_or_else(|| ChannelId::temporary_from_entropy_source(entropy_source));
22982304

22992305
let holder_signer = ChannelSignerType::Ecdsa(holder_signer);
2300-
let holder_commitment_point = HolderCommitmentPoint::new(&holder_signer, &secp_ctx);
2306+
// Unwrap here since it gets removed in the next commit
2307+
let holder_commitment_point = HolderCommitmentPoint::new(&holder_signer, &secp_ctx).unwrap();
23012308

23022309
Ok(Self {
23032310
user_id,
@@ -4214,6 +4221,7 @@ pub(super) struct DualFundingChannelContext {
42144221
pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
42154222
pub context: ChannelContext<SP>,
42164223
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
4224+
holder_commitment_point: HolderCommitmentPoint,
42174225
}
42184226

42194227
#[cfg(any(test, fuzzing))]
@@ -8297,28 +8305,31 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
82978305
let holder_signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
82988306
let pubkeys = holder_signer.pubkeys().clone();
82998307

8300-
let chan = Self {
8301-
context: ChannelContext::new_for_outbound_channel(
8302-
fee_estimator,
8303-
entropy_source,
8304-
signer_provider,
8305-
counterparty_node_id,
8306-
their_features,
8307-
channel_value_satoshis,
8308-
push_msat,
8309-
user_id,
8310-
config,
8311-
current_chain_height,
8312-
outbound_scid_alias,
8313-
temporary_channel_id,
8314-
holder_selected_channel_reserve_satoshis,
8315-
channel_keys_id,
8316-
holder_signer,
8317-
pubkeys,
8318-
logger,
8319-
)?,
8320-
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }
8308+
let context = ChannelContext::new_for_outbound_channel(
8309+
fee_estimator,
8310+
entropy_source,
8311+
signer_provider,
8312+
counterparty_node_id,
8313+
their_features,
8314+
channel_value_satoshis,
8315+
push_msat,
8316+
user_id,
8317+
config,
8318+
current_chain_height,
8319+
outbound_scid_alias,
8320+
temporary_channel_id,
8321+
holder_selected_channel_reserve_satoshis,
8322+
channel_keys_id,
8323+
holder_signer,
8324+
pubkeys,
8325+
logger,
8326+
)?;
8327+
let unfunded_context = UnfundedChannelContext {
8328+
unfunded_channel_age_ticks: 0,
8329+
holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
83218330
};
8331+
8332+
let chan = Self { context, unfunded_context };
83228333
Ok(chan)
83238334
}
83248335

@@ -8510,9 +8521,11 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
85108521

85118522
log_info!(logger, "Received funding_signed from peer for channel {}", &self.context.channel_id());
85128523

8524+
let holder_commitment_point = self.context.holder_commitment_point;
85138525
let mut channel = Channel {
85148526
context: self.context,
85158527
interactive_tx_signing_session: None,
8528+
holder_commitment_point,
85168529
};
85178530

85188531
let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some();
@@ -8600,29 +8613,31 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
86008613
htlc_basepoint: HtlcBasepoint::from(msg.common_fields.htlc_basepoint)
86018614
};
86028615

8603-
let chan = Self {
8604-
context: ChannelContext::new_for_inbound_channel(
8605-
fee_estimator,
8606-
entropy_source,
8607-
signer_provider,
8608-
counterparty_node_id,
8609-
their_features,
8610-
user_id,
8611-
config,
8612-
current_chain_height,
8613-
&&logger,
8614-
is_0conf,
8615-
0,
8616-
8617-
counterparty_pubkeys,
8618-
channel_type,
8619-
holder_selected_channel_reserve_satoshis,
8620-
msg.channel_reserve_satoshis,
8621-
msg.push_msat,
8622-
msg.common_fields.clone(),
8623-
)?,
8624-
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
8616+
let context = ChannelContext::new_for_inbound_channel(
8617+
fee_estimator,
8618+
entropy_source,
8619+
signer_provider,
8620+
counterparty_node_id,
8621+
their_features,
8622+
user_id,
8623+
config,
8624+
current_chain_height,
8625+
&&logger,
8626+
is_0conf,
8627+
0,
8628+
8629+
counterparty_pubkeys,
8630+
channel_type,
8631+
holder_selected_channel_reserve_satoshis,
8632+
msg.channel_reserve_satoshis,
8633+
msg.push_msat,
8634+
msg.common_fields.clone(),
8635+
)?;
8636+
let unfunded_context = UnfundedChannelContext {
8637+
unfunded_channel_age_ticks: 0,
8638+
holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
86258639
};
8640+
let chan = Self { context, unfunded_context };
86268641
Ok(chan)
86278642
}
86288643

@@ -8735,9 +8750,11 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
87358750

87368751
// Promote the channel to a full-fledged one now that we have updated the state and have a
87378752
// `ChannelMonitor`.
8753+
let holder_commitment_point = self.context.holder_commitment_point;
87388754
let mut channel = Channel {
87398755
context: self.context,
87408756
interactive_tx_signing_session: None,
8757+
holder_commitment_point,
87418758
};
87428759
let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some();
87438760
channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
@@ -8784,27 +8801,32 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
87848801
"Provided current chain height of {} doesn't make sense for a height-based timelock for the funding transaction",
87858802
current_chain_height) })?;
87868803

8804+
let context = ChannelContext::new_for_outbound_channel(
8805+
fee_estimator,
8806+
entropy_source,
8807+
signer_provider,
8808+
counterparty_node_id,
8809+
their_features,
8810+
funding_satoshis,
8811+
0,
8812+
user_id,
8813+
config,
8814+
current_chain_height,
8815+
outbound_scid_alias,
8816+
temporary_channel_id,
8817+
holder_selected_channel_reserve_satoshis,
8818+
channel_keys_id,
8819+
holder_signer,
8820+
pubkeys,
8821+
logger,
8822+
)?;
8823+
let unfunded_context = UnfundedChannelContext {
8824+
unfunded_channel_age_ticks: 0,
8825+
holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
8826+
};
87878827
let chan = Self {
8788-
context: ChannelContext::new_for_outbound_channel(
8789-
fee_estimator,
8790-
entropy_source,
8791-
signer_provider,
8792-
counterparty_node_id,
8793-
their_features,
8794-
funding_satoshis,
8795-
0,
8796-
user_id,
8797-
config,
8798-
current_chain_height,
8799-
outbound_scid_alias,
8800-
temporary_channel_id,
8801-
holder_selected_channel_reserve_satoshis,
8802-
channel_keys_id,
8803-
holder_signer,
8804-
pubkeys,
8805-
logger,
8806-
)?,
8807-
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
8828+
context,
8829+
unfunded_context,
88088830
dual_funding_context: DualFundingChannelContext {
88098831
our_funding_satoshis: funding_satoshis,
88108832
funding_tx_locktime,
@@ -8880,9 +8902,13 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
88808902
}
88818903

88828904
pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
8905+
let holder_commitment_point = self.unfunded_context.holder_commitment_point.ok_or(ChannelError::close(
8906+
format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
8907+
self.context.channel_id())))?;
88838908
let channel = Channel {
88848909
context: self.context,
88858910
interactive_tx_signing_session: Some(signing_session),
8911+
holder_commitment_point,
88868912
};
88878913

88888914
Ok(channel)
@@ -8993,11 +9019,15 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
89939019
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) }
89949020
)))?);
89959021

9022+
let unfunded_context = UnfundedChannelContext {
9023+
unfunded_channel_age_ticks: 0,
9024+
holder_commitment_point: HolderCommitmentPoint::new(&context.holder_signer, &context.secp_ctx),
9025+
};
89969026
Ok(Self {
89979027
context,
89989028
dual_funding_context,
89999029
interactive_tx_constructor,
9000-
unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
9030+
unfunded_context,
90019031
})
90029032
}
90039033

@@ -9074,9 +9104,13 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
90749104
}
90759105

90769106
pub fn into_channel(self, signing_session: InteractiveTxSigningSession) -> Result<Channel<SP>, ChannelError>{
9107+
let holder_commitment_point = self.unfunded_context.holder_commitment_point.ok_or(ChannelError::close(
9108+
format!("Expected to have holder commitment points available upon finishing interactive tx construction for channel {}",
9109+
self.context.channel_id())))?;
90779110
let channel = Channel {
90789111
context: self.context,
90799112
interactive_tx_signing_session: Some(signing_session),
9113+
holder_commitment_point,
90809114
};
90819115

90829116
Ok(channel)
@@ -10157,6 +10191,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1015710191
next_funding_txid: None,
1015810192
},
1015910193
interactive_tx_signing_session: None,
10194+
holder_commitment_point,
1016010195
})
1016110196
}
1016210197
}

0 commit comments

Comments
 (0)