Skip to content

Commit b8179e0

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 0917ebf commit b8179e0

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
@@ -2070,6 +2070,35 @@ impl KeysManager {
20702070
self.node_secret
20712071
}
20722072

2073+
/// Gets the set of possible `script_pubkey`s which can appear on chain for our
2074+
/// non-HTLC-encumbered balance if our counterparty force-closes the channel.
2075+
///
2076+
/// Only channels opened or spliced when using a [`KeysManager`] with the
2077+
/// `v2_remote_key_derivation` argument to [`KeysManager::new`] will close to such scripts,
2078+
/// other channels will close to a randomly-generated `script_pubkey`.
2079+
pub fn possible_v2_counterparty_closed_balance_spks<C: Signing>(
2080+
&self, secp_ctx: &Secp256k1<C>,
2081+
) -> Vec<ScriptBuf> {
2082+
let mut res = Vec::with_capacity(usize::from(STATIC_PAYMENT_KEY_COUNT) * 2);
2083+
let static_remote_key_features = ChannelTypeFeatures::only_static_remote_key();
2084+
let mut zero_fee_htlc_features = ChannelTypeFeatures::only_static_remote_key();
2085+
zero_fee_htlc_features.set_anchors_zero_fee_htlc_tx_required();
2086+
for idx in 0..STATIC_PAYMENT_KEY_COUNT {
2087+
let key = self
2088+
.static_payment_key
2089+
.derive_priv(
2090+
&self.secp_ctx,
2091+
&ChildNumber::from_hardened_idx(u32::from(idx)).expect("key space exhausted"),
2092+
)
2093+
.expect("Your RNG is busted")
2094+
.private_key;
2095+
let pubkey = PublicKey::from_secret_key(secp_ctx, &key);
2096+
res.push(get_counterparty_payment_script(&static_remote_key_features, &pubkey));
2097+
res.push(get_counterparty_payment_script(&zero_fee_htlc_features, &pubkey));
2098+
}
2099+
res
2100+
}
2101+
20732102
fn derive_payment_key_v2(&self, params: &[u8; 32]) -> SecretKey {
20742103
let mut eight_bytes = [0; 8];
20752104
eight_bytes.copy_from_slice(&params[0..8]);
@@ -2171,6 +2200,15 @@ impl KeysManager {
21712200
let signer = self.derive_channel_keys(&descriptor.channel_keys_id);
21722201
keys_cache = Some((signer, descriptor.channel_keys_id));
21732202
}
2203+
#[cfg(test)]
2204+
if self.v2_remote_key_derivation {
2205+
// In tests, we don't have to deal with upgrades from V1 sighers with
2206+
// `v2_remote_key_derivation` set, so use this opportunity to test
2207+
// `possible_v2_counterparty_closed_balance_spks`.
2208+
let possible_spks =
2209+
self.possible_v2_counterparty_closed_balance_spks(secp_ctx);
2210+
assert!(possible_spks.contains(&descriptor.output.script_pubkey));
2211+
}
21742212
let witness = keys_cache.as_ref().unwrap().0.sign_counterparty_payment_input(
21752213
&psbt.unsigned_tx,
21762214
input_idx,

0 commit comments

Comments
 (0)