/target/
+/hfuzz_target/
/net-tokio/target/
**/*.rs.bk
Cargo.lock
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,
})
}
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 {
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,
}
})
}
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;
/// 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.
///
/// 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)]
/// 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 {
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);
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());
}
}
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
delayed_payment_base_key,
htlc_base_key,
commitment_seed,
- remote_funding_pubkey: None,
+ remote_channel_pubkeys: None,
}
}
/// 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,
pub 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)?,
use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
use ln::channelmonitor::ChannelMonitor;
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT};
-use ln::chan_utils::{LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript};
+use ln::chan_utils::{LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys};
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use chain::transaction::OutPoint;
/// Assumes chain_hash has already been checked and corresponds with what we expect!
pub fn new_from_req(fee_estimator: &FeeEstimator, keys_provider: &Arc<KeysInterface<ChanKeySigner = ChanSigner>>, their_node_id: PublicKey, their_features: InitFeatures, msg: &msgs::OpenChannel, user_id: u64, logger: Arc<Logger>, config: &UserConfig) -> Result<Channel<ChanSigner>, ChannelError> {
let mut chan_keys = keys_provider.get_channel_keys(true);
- chan_keys.set_remote_funding_pubkey(&msg.funding_pubkey);
+ let channel_pubkeys = ChannelPublicKeys {
+ funding_pubkey: msg.funding_pubkey,
+ revocation_basepoint: msg.revocation_basepoint,
+ payment_basepoint: msg.payment_basepoint,
+ delayed_payment_basepoint: msg.delayed_payment_basepoint,
+ htlc_basepoint: msg.htlc_basepoint
+ };
+ chan_keys.set_remote_channel_pubkeys(&channel_pubkeys);
let mut local_config = (*config).channel_options.clone();
if config.own_channel_config.our_to_self_delay < BREAKDOWN_TIMEOUT {
self.channel_monitor.set_basic_channel_info(&msg.htlc_basepoint, &msg.delayed_payment_basepoint, msg.to_self_delay, funding_redeemscript, self.channel_value_satoshis, obscure_factor);
self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32;
- self.local_keys.set_remote_funding_pubkey(&msg.funding_pubkey);
+ let channel_pubkeys = ChannelPublicKeys {
+ funding_pubkey: msg.funding_pubkey,
+ revocation_basepoint: msg.revocation_basepoint,
+ payment_basepoint: msg.payment_basepoint,
+ delayed_payment_basepoint: msg.delayed_payment_basepoint,
+ htlc_basepoint: msg.htlc_basepoint
+ };
+ self.local_keys.set_remote_channel_pubkeys(&channel_pubkeys);
Ok(())
}
// These aren't set in the test vectors:
revocation_base_key: SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
commitment_seed: [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
- remote_funding_pubkey: None,
+ remote_channel_pubkeys: None,
};
assert_eq!(PublicKey::from_secret_key(&secp_ctx, chan_keys.funding_key()).serialize()[..],
hex::decode("023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb").unwrap()[..]);
-use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys};
+use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, ChannelPublicKeys};
use ln::msgs;
use chain::keysinterface::{ChannelKeys, InMemoryChannelKeys};
}
}
}
+
+impl EnforcingChannelKeys {
+ fn check_keys<T: secp256k1::Signing + secp256k1::Verification>(&self, secp_ctx: &Secp256k1<T>,
+ keys: &TxCreationKeys) {
+ let revocation_base = PublicKey::from_secret_key(secp_ctx, &self.inner.revocation_base_key);
+ let payment_base = PublicKey::from_secret_key(secp_ctx, &self.inner.payment_base_key);
+ let htlc_base = PublicKey::from_secret_key(secp_ctx, &self.inner.htlc_base_key);
+
+ let remote_points = self.inner.remote_channel_pubkeys.as_ref().unwrap();
+
+ let keys_expected = TxCreationKeys::new(secp_ctx,
+ &keys.per_commitment_point,
+ &remote_points.delayed_payment_basepoint,
+ &remote_points.htlc_basepoint,
+ &revocation_base,
+ &payment_base,
+ &htlc_base).unwrap();
+ if keys != &keys_expected { panic!("derived different per-tx keys") }
+ }
+}
+
impl ChannelKeys for EnforcingChannelKeys {
fn funding_key(&self) -> &SecretKey { self.inner.funding_key() }
fn revocation_base_key(&self) -> &SecretKey { self.inner.revocation_base_key() }
fn htlc_base_key(&self) -> &SecretKey { self.inner.htlc_base_key() }
fn commitment_seed(&self) -> &[u8; 32] { self.inner.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>), ()> {
- if commitment_tx.input.len() != 1 { panic!(); }
+ 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 { panic!("lightning commitment transactions have a single input"); }
+ self.check_keys(secp_ctx, keys);
let obscured_commitment_transaction_number = (commitment_tx.lock_time & 0xffffff) as u64 | ((commitment_tx.input[0].sequence as u64 & 0xffffff) << 3*8);
{
self.inner.sign_channel_announcement(msg, secp_ctx)
}
- fn set_remote_funding_pubkey(&mut self, key: &PublicKey) {
- self.inner.set_remote_funding_pubkey(key)
+ fn set_remote_channel_pubkeys(&mut self, channel_pubkeys: &ChannelPublicKeys) {
+ self.inner.set_remote_channel_pubkeys(channel_pubkeys)
}
}
+
impl_writeable!(EnforcingChannelKeys, 0, {
inner,
commitment_number_obscure_and_last