Skip to content

Provide remote channel public keys to signer #451

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 3 commits into from
Jan 20, 2020
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/target/
/hfuzz_target/
/net-tokio/target/
**/*.rs.bk
Cargo.lock
Expand Down
2 changes: 1 addition & 1 deletion fuzz/src/chanmon_consistency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl KeysInterface for KeyProvider {
delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, self.node_id]).unwrap(),
htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, self.node_id]).unwrap(),
commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, self.node_id],
remote_funding_pubkey: None,
remote_channel_pubkeys: None,
})
}

Expand Down
4 changes: 2 additions & 2 deletions fuzz/src/full_stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ impl KeysInterface for KeyProvider {
delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, ctr]).unwrap(),
htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, ctr]).unwrap(),
commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, ctr],
remote_funding_pubkey: None,
remote_channel_pubkeys: None,
}
} else {
InMemoryChannelKeys {
Expand All @@ -267,7 +267,7 @@ impl KeysInterface for KeyProvider {
delayed_payment_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, ctr]).unwrap(),
htlc_base_key: SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, ctr]).unwrap(),
commitment_seed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, ctr],
remote_funding_pubkey: None,
remote_channel_pubkeys: None,
}
})
}
Expand Down
26 changes: 13 additions & 13 deletions lightning/src/chain/keysinterface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use util::logger::Logger;
use util::ser::Writeable;

use ln::chan_utils;
use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript};
use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys};
use ln::msgs;

use std::sync::Arc;
Expand Down Expand Up @@ -142,7 +142,7 @@ pub trait ChannelKeys : Send {
/// TODO: Document the things someone using this interface should enforce before signing.
/// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
/// making the callee generate it via some util function we expose)!
fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;

/// Create a signature for a (proposed) closing transaction.
///
Expand All @@ -158,11 +158,11 @@ pub trait ChannelKeys : Send {
/// protocol.
fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;

/// Set the remote funding key. This is done immediately on incoming channels
/// Set the remote channel basepoints. This is done immediately on incoming channels
/// and as soon as the channel is accepted on outgoing channels.
///
/// Will be called before any signatures are applied.
fn set_remote_funding_pubkey(&mut self, key: &PublicKey);
fn set_remote_channel_pubkeys(&mut self, channel_points: &ChannelPublicKeys);
}

#[derive(Clone)]
Expand All @@ -181,7 +181,7 @@ pub struct InMemoryChannelKeys {
/// Commitment seed
pub commitment_seed: [u8; 32],
/// Remote funding pubkey
pub remote_funding_pubkey: Option<PublicKey>,
pub remote_channel_pubkeys: Option<ChannelPublicKeys>,
}

impl ChannelKeys for InMemoryChannelKeys {
Expand All @@ -192,12 +192,12 @@ impl ChannelKeys for InMemoryChannelKeys {
fn htlc_base_key(&self) -> &SecretKey { &self.htlc_base_key }
fn commitment_seed(&self) -> &[u8; 32] { &self.commitment_seed }

fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
fn sign_remote_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, channel_value_satoshis: u64, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
if commitment_tx.input.len() != 1 { return Err(()); }

let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
let remote_funding_pubkey = self.remote_funding_pubkey.as_ref().expect("must set remote funding key before signing");
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, remote_funding_pubkey);
let remote_channel_pubkeys = self.remote_channel_pubkeys.as_ref().expect("must set remote channel pubkeys before signing");
let channel_funding_redeemscript = make_funding_redeemscript(&funding_pubkey, &remote_channel_pubkeys.funding_pubkey);

let commitment_sighash = hash_to_message!(&bip143::SighashComponents::new(&commitment_tx).sighash_all(&commitment_tx.input[0], &channel_funding_redeemscript, channel_value_satoshis)[..]);
let commitment_sig = secp_ctx.sign(&commitment_sighash, &self.funding_key);
Expand Down Expand Up @@ -236,9 +236,9 @@ impl ChannelKeys for InMemoryChannelKeys {
Ok(secp_ctx.sign(&msghash, &self.funding_key))
}

fn set_remote_funding_pubkey(&mut self, key: &PublicKey) {
assert!(self.remote_funding_pubkey.is_none(), "Already set remote funding key");
self.remote_funding_pubkey = Some(*key);
fn set_remote_channel_pubkeys(&mut self, channel_pubkeys: &ChannelPublicKeys) {
assert!(self.remote_channel_pubkeys.is_none(), "Already set remote channel pubkeys");
self.remote_channel_pubkeys = Some(channel_pubkeys.clone());
}
}

Expand All @@ -249,7 +249,7 @@ impl_writeable!(InMemoryChannelKeys, 0, {
delayed_payment_base_key,
htlc_base_key,
commitment_seed,
remote_funding_pubkey
remote_channel_pubkeys
});

/// Simple KeysInterface implementor that takes a 32-byte seed for use as a BIP 32 extended key
Expand Down Expand Up @@ -398,7 +398,7 @@ impl KeysInterface for KeysManager {
delayed_payment_base_key,
htlc_base_key,
commitment_seed,
remote_funding_pubkey: None,
remote_channel_pubkeys: None,
}
}

Expand Down
47 changes: 40 additions & 7 deletions lightning/src/ln/chan_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use ln::channelmanager::{PaymentHash, PaymentPreimage};
use ln::msgs::DecodeError;
use util::ser::{Readable, Writeable, Writer, WriterWriteAdaptor};

use secp256k1::key::{SecretKey,PublicKey};
use secp256k1::key::{SecretKey, PublicKey};
use secp256k1::{Secp256k1, Signature};
use secp256k1;

Expand Down Expand Up @@ -118,24 +118,57 @@ pub(super) fn derive_public_revocation_key<T: secp256k1::Verification>(secp_ctx:

/// The set of public keys which are used in the creation of one commitment transaction.
/// These are derived from the channel base keys and per-commitment data.
#[derive(PartialEq)]
pub struct TxCreationKeys {
/// The per-commitment public key which was used to derive the other keys.
pub per_commitment_point: PublicKey,
/// The revocation key which is used to allow the owner of the commitment transaction to
/// provide their counterparty the ability to punish them if they broadcast an old state.
pub revocation_key: PublicKey,
pub(crate) revocation_key: PublicKey,
/// A's HTLC Key
pub a_htlc_key: PublicKey,
pub(crate) a_htlc_key: PublicKey,
/// B's HTLC Key
pub b_htlc_key: PublicKey,
pub(crate) b_htlc_key: PublicKey,
/// A's Payment Key (which isn't allowed to be spent from for some delay)
pub a_delayed_payment_key: PublicKey,
pub(crate) a_delayed_payment_key: PublicKey,
/// B's Payment Key
pub b_payment_key: PublicKey,
pub(crate) b_payment_key: PublicKey,
}

/// One counterparty's public keys which do not change over the life of a channel.
#[derive(Clone)]
pub struct ChannelPublicKeys {
/// The public key which is used to sign all commitment transactions, as it appears in the
/// on-chain channel lock-in 2-of-2 multisig output.
pub funding_pubkey: PublicKey,
/// The base point which is used (with derive_public_revocation_key) to derive per-commitment
/// revocation keys. The per-commitment revocation private key is then revealed by the owner of
/// a commitment transaction so that their counterparty can claim all available funds if they
/// broadcast an old state.
pub revocation_basepoint: PublicKey,
/// The base point which is used (with derive_public_key) to derive a per-commitment payment
/// public key which receives immediately-spendable non-HTLC-encumbered funds.
pub payment_basepoint: PublicKey,
/// The base point which is used (with derive_public_key) to derive a per-commitment payment
/// public key which receives non-HTLC-encumbered funds which are only available for spending
/// after some delay (or can be claimed via the revocation path).
pub delayed_payment_basepoint: PublicKey,
/// The base point which is used (with derive_public_key) to derive a per-commitment public key
/// which is used to encumber HTLC-in-flight outputs.
pub htlc_basepoint: PublicKey,
}

impl_writeable!(ChannelPublicKeys, 33*5, {
funding_pubkey,
revocation_basepoint,
payment_basepoint,
delayed_payment_basepoint,
htlc_basepoint
});


impl TxCreationKeys {
pub(super) fn new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, a_delayed_payment_base: &PublicKey, a_htlc_base: &PublicKey, b_revocation_base: &PublicKey, b_payment_base: &PublicKey, b_htlc_base: &PublicKey) -> Result<TxCreationKeys, secp256k1::Error> {
pub(crate) fn new<T: secp256k1::Signing + secp256k1::Verification>(secp_ctx: &Secp256k1<T>, per_commitment_point: &PublicKey, a_delayed_payment_base: &PublicKey, a_htlc_base: &PublicKey, b_revocation_base: &PublicKey, b_payment_base: &PublicKey, b_htlc_base: &PublicKey) -> Result<TxCreationKeys, secp256k1::Error> {
Ok(TxCreationKeys {
per_commitment_point: per_commitment_point.clone(),
revocation_key: derive_public_revocation_key(&secp_ctx, &per_commitment_point, &b_revocation_base)?,
Expand Down
Loading