Skip to content

Commit fd969c4

Browse files
committed
Add a method to fetch all possible remote-closure script_pubkeys
In the previous commit we (finally) allowed users to opt into a static `remote_key` derivation scheme, enabling them to scan the chain for funds on counterparty commitment transactions without any state at all. This is only possible, however, of course, if they have the full list of scripts to scan the chain for, which we expose here.
1 parent 189b8ac commit fd969c4

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

lightning/src/sign/mod.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,6 +2074,35 @@ impl KeysManager {
20742074
self.node_secret
20752075
}
20762076

2077+
/// Gets the set of possible `script_pubkey`s which can appear on chain for our
2078+
/// non-HTLC-encumbered balance if our counterparty force-closes the channel.
2079+
///
2080+
/// Only channels opened when using a [`KeysManager`] with the `v2_remote_key_derivation`
2081+
/// argument to [`KeysManager::new`] set, or any spliced channels will close to such scripts,
2082+
/// other channels will close to a randomly-generated `script_pubkey`.
2083+
pub fn possible_v2_counterparty_closed_balance_spks<C: Signing>(
2084+
&self, secp_ctx: &Secp256k1<C>,
2085+
) -> Vec<ScriptBuf> {
2086+
let mut res = Vec::with_capacity(usize::from(STATIC_PAYMENT_KEY_COUNT) * 2);
2087+
let static_remote_key_features = ChannelTypeFeatures::only_static_remote_key();
2088+
let mut zero_fee_htlc_features = ChannelTypeFeatures::only_static_remote_key();
2089+
zero_fee_htlc_features.set_anchors_zero_fee_htlc_tx_required();
2090+
for idx in 0..STATIC_PAYMENT_KEY_COUNT {
2091+
let key = self
2092+
.static_payment_key
2093+
.derive_priv(
2094+
&self.secp_ctx,
2095+
&ChildNumber::from_hardened_idx(u32::from(idx)).expect("key space exhausted"),
2096+
)
2097+
.expect("Your RNG is busted")
2098+
.private_key;
2099+
let pubkey = PublicKey::from_secret_key(secp_ctx, &key);
2100+
res.push(get_counterparty_payment_script(&static_remote_key_features, &pubkey));
2101+
res.push(get_counterparty_payment_script(&zero_fee_htlc_features, &pubkey));
2102+
}
2103+
res
2104+
}
2105+
20772106
fn derive_payment_key_v2(&self, key_idx: u64) -> SecretKey {
20782107
let idx = key_idx % u64::from(STATIC_PAYMENT_KEY_COUNT);
20792108
self.static_payment_key
@@ -2176,6 +2205,15 @@ impl KeysManager {
21762205
let signer = self.derive_channel_keys(&descriptor.channel_keys_id);
21772206
keys_cache = Some((signer, descriptor.channel_keys_id));
21782207
}
2208+
#[cfg(test)]
2209+
if self.v2_remote_key_derivation {
2210+
// In tests, we don't have to deal with upgrades from V1 signers with
2211+
// `v2_remote_key_derivation` set, so use this opportunity to test
2212+
// `possible_v2_counterparty_closed_balance_spks`.
2213+
let possible_spks =
2214+
self.possible_v2_counterparty_closed_balance_spks(secp_ctx);
2215+
assert!(possible_spks.contains(&descriptor.output.script_pubkey));
2216+
}
21792217
let witness = keys_cache.as_ref().unwrap().0.sign_counterparty_payment_input(
21802218
&psbt.unsigned_tx,
21812219
input_idx,

0 commit comments

Comments
 (0)