Skip to content

ChannelKeys provides individual commitment secrets #652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions lightning/src/chain/keysinterface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,9 @@ impl Readable for SpendableOutputDescriptor {
// TODO: We should remove Clone by instead requesting a new ChannelKeys copy when we create
// ChannelMonitors instead of expecting to clone the one out of the Channel into the monitors.
pub trait ChannelKeys : Send+Clone {
/// Gets the commitment seed
fn commitment_seed(&self) -> &[u8; 32];
/// Gets the commitment seed for a specific commitment number
/// Note that the commitment number starts at (1 << 48) - 1 and counts backwards
fn commitment_secret(&self, idx: u64) -> [u8; 32];
/// Gets the local channel public keys and basepoints
fn pubkeys(&self) -> &ChannelPublicKeys;
/// Gets arbitrary identifiers describing the set of keys which are provided back to you in
Expand Down Expand Up @@ -404,7 +405,10 @@ impl InMemoryChannelKeys {
}

impl ChannelKeys for InMemoryChannelKeys {
fn commitment_seed(&self) -> &[u8; 32] { &self.commitment_seed }
fn commitment_secret(&self, idx: u64) -> [u8; 32] {
chan_utils::build_commitment_secret(&self.commitment_seed, idx)
}

fn pubkeys(&self) -> &ChannelPublicKeys { &self.local_channel_pubkeys }
fn key_derivation_params(&self) -> (u64, u64) { self.key_derivation_params }

Expand Down
3 changes: 2 additions & 1 deletion lightning/src/ln/chan_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ impl HTLCType {
// Various functions for key derivation and transaction creation for use within channels. Primarily
// used in Channel and ChannelMonitor.

pub(super) fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32] {
/// Build the commitment secret from the seed and the commitment number
pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32] {
let mut res: [u8; 32] = commitment_seed.clone();
for i in 0..48 {
let bitpos = 47 - i;
Expand Down
8 changes: 4 additions & 4 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
// Utilities to derive keys:

fn build_local_commitment_secret(&self, idx: u64) -> SecretKey {
let res = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), idx);
let res = self.local_keys.commitment_secret(idx);
SecretKey::from_slice(&res).unwrap()
}

Expand Down Expand Up @@ -2021,7 +2021,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
}

let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number - 1));
let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), self.cur_local_commitment_transaction_number + 1);
let per_commitment_secret = self.local_keys.commitment_secret(self.cur_local_commitment_transaction_number + 1);

// Update state now that we've passed all the can-fail calls...
let mut need_our_commitment = false;
Expand Down Expand Up @@ -2660,7 +2660,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {

fn get_last_revoke_and_ack(&self) -> msgs::RevokeAndACK {
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number));
let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), self.cur_local_commitment_transaction_number + 2);
let per_commitment_secret = self.local_keys.commitment_secret(self.cur_local_commitment_transaction_number + 2);
msgs::RevokeAndACK {
channel_id: self.channel_id,
per_commitment_secret,
Expand Down Expand Up @@ -2743,7 +2743,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
if msg.next_remote_commitment_number > 0 {
match msg.data_loss_protect {
OptionalField::Present(ref data_loss) => {
if chan_utils::build_commitment_secret(self.local_keys.commitment_seed(), INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1) != data_loss.your_last_per_commitment_secret {
if self.local_keys.commitment_secret(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1) != data_loss.your_last_per_commitment_secret {
return Err(ChannelError::Close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided"));
}
if msg.next_remote_commitment_number > INITIAL_COMMITMENT_NUMBER - self.cur_local_commitment_transaction_number {
Expand Down
29 changes: 15 additions & 14 deletions lightning/src/ln/functional_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1599,29 +1599,29 @@ fn test_fee_spike_violation_fails_htlc() {

let feerate_per_kw = get_feerate!(nodes[0], chan.2);

const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;

// Get the EnforcingChannelKeys for each channel, which will be used to (1) get the keys
// needed to sign the new commitment tx and (2) sign the new commitment tx.
let (local_revocation_basepoint, local_htlc_basepoint, local_payment_point, local_chan_commitment_seed) = {
let (local_revocation_basepoint, local_htlc_basepoint, local_payment_point, local_secret, local_secret2) = {
let chan_lock = nodes[0].node.channel_state.lock().unwrap();
let local_chan = chan_lock.by_id.get(&chan.2).unwrap();
let chan_keys = local_chan.get_local_keys();
let pubkeys = chan_keys.pubkeys();
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint, pubkeys.payment_point, *chan_keys.commitment_seed())
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint, pubkeys.payment_point,
chan_keys.commitment_secret(INITIAL_COMMITMENT_NUMBER), chan_keys.commitment_secret(INITIAL_COMMITMENT_NUMBER - 2))
};
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_payment_point, remote_chan_commitment_seed) = {
let (remote_delayed_payment_basepoint, remote_htlc_basepoint, remote_payment_point, remote_secret1) = {
let chan_lock = nodes[1].node.channel_state.lock().unwrap();
let remote_chan = chan_lock.by_id.get(&chan.2).unwrap();
let chan_keys = remote_chan.get_local_keys();
let pubkeys = chan_keys.pubkeys();
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint, pubkeys.payment_point, *chan_keys.commitment_seed())
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint, pubkeys.payment_point,
chan_keys.commitment_secret(INITIAL_COMMITMENT_NUMBER - 1))
};

// Assemble the set of keys we can use for signatures for our commitment_signed message.
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
let commitment_secret = {
let res = chan_utils::build_commitment_secret(&remote_chan_commitment_seed, INITIAL_COMMITMENT_NUMBER - 1);
SecretKey::from_slice(&res).unwrap()
};
let commitment_secret = SecretKey::from_slice(&remote_secret1).unwrap();
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &commitment_secret);
let commit_tx_keys = chan_utils::TxCreationKeys::new(&secp_ctx, &per_commitment_point, &remote_delayed_payment_basepoint,
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint).unwrap();
Expand Down Expand Up @@ -1706,8 +1706,8 @@ fn test_fee_spike_violation_fails_htlc() {
let _ = nodes[1].node.get_and_clear_pending_msg_events();

// Send the RAA to nodes[1].
let per_commitment_secret = chan_utils::build_commitment_secret(&local_chan_commitment_seed, INITIAL_COMMITMENT_NUMBER);
let next_secret = SecretKey::from_slice(&chan_utils::build_commitment_secret(&local_chan_commitment_seed, INITIAL_COMMITMENT_NUMBER - 2)).unwrap();
let per_commitment_secret = local_secret;
let next_secret = SecretKey::from_slice(&local_secret2).unwrap();
let next_per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &next_secret);
let raa_msg = msgs::RevokeAndACK{ channel_id: chan.2, per_commitment_secret, next_per_commitment_point};
nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &raa_msg);
Expand Down Expand Up @@ -8125,11 +8125,12 @@ fn test_counterparty_raa_skip_no_crash() {
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).2;

let commitment_seed = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&channel_id).unwrap().local_keys.commitment_seed().clone();
let mut guard = nodes[0].node.channel_state.lock().unwrap();
let local_keys = &guard.by_id.get_mut(&channel_id).unwrap().local_keys;
const INITIAL_COMMITMENT_NUMBER: u64 = (1 << 48) - 1;
let next_per_commitment_point = PublicKey::from_secret_key(&Secp256k1::new(),
&SecretKey::from_slice(&chan_utils::build_commitment_secret(&commitment_seed, INITIAL_COMMITMENT_NUMBER - 2)).unwrap());
let per_commitment_secret = chan_utils::build_commitment_secret(&commitment_seed, INITIAL_COMMITMENT_NUMBER);
&SecretKey::from_slice(&local_keys.commitment_secret(INITIAL_COMMITMENT_NUMBER - 2)).unwrap());
let per_commitment_secret = local_keys.commitment_secret(INITIAL_COMMITMENT_NUMBER);

nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(),
&msgs::RevokeAndACK { channel_id, per_commitment_secret, next_per_commitment_point });
Expand Down
2 changes: 1 addition & 1 deletion lightning/src/util/enforcing_trait_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl EnforcingChannelKeys {
}

impl ChannelKeys for EnforcingChannelKeys {
fn commitment_seed(&self) -> &[u8; 32] { self.inner.commitment_seed() }
fn commitment_secret(&self, idx: u64) -> [u8; 32] { self.inner.commitment_secret(idx) }
fn pubkeys(&self) -> &ChannelPublicKeys { self.inner.pubkeys() }
fn key_derivation_params(&self) -> (u64, u64) { self.inner.key_derivation_params() }

Expand Down