use bitcoin::util::bip32::{ExtendedPrivKey, ExtendedPubKey, ChildNumber};
use bitcoin::util::bip143;
-use bitcoin_hashes::{Hash, HashEngine};
-use bitcoin_hashes::sha256::HashEngine as Sha256State;
-use bitcoin_hashes::sha256::Hash as Sha256;
-use bitcoin_hashes::sha256d::Hash as Sha256dHash;
-use bitcoin_hashes::hash160::Hash as Hash160;
+use bitcoin::hashes::{Hash, HashEngine};
+use bitcoin::hashes::sha256::HashEngine as Sha256State;
+use bitcoin::hashes::sha256::Hash as Sha256;
+use bitcoin::hashes::sha256d::Hash as Sha256dHash;
+use bitcoin::hash_types::WPubkeyHash;
-use secp256k1::key::{SecretKey, PublicKey};
-use secp256k1::{Secp256k1, Signature, Signing};
-use secp256k1;
+use bitcoin::secp256k1::key::{SecretKey, PublicKey};
+use bitcoin::secp256k1::{Secp256k1, Signature, Signing};
+use bitcoin::secp256k1;
use util::byte_utils;
use util::logger::Logger;
use ln::chan_utils;
use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, LocalCommitmentTransaction};
-use ln::channelmanager::PaymentPreimage;
use ln::msgs;
use std::sync::Arc;
/// The output which is referenced by the given outpoint
output: TxOut,
},
+ // TODO: Note that because key is now static and exactly what is provided by us, we should drop
+ // this in favor of StaticOutput:
/// An output to a P2WPKH, spendable exclusively by the given private key.
/// The witness in the spending input, is, thus, simply:
/// <BIP 143 signature generated with the given key> <public key derived from the given key>
/// Readable/Writable to serialize out a unique reference to this set of keys so
/// that you can serialize the full ChannelManager object.
///
-/// (TODO: We shouldn't require that, and should have an API to get them at deser time, due mostly
-/// to the possibility of reentrancy issues by calling the user's code during our deserialization
-/// routine).
-/// 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.
+// (TODO: We shouldn't require that, and should have an API to get them at deser time, due mostly
+// to the possibility of reentrancy issues by calling the user's code during our deserialization
+// routine).
+// 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 private key for the anchor tx
fn funding_key<'a>(&'a self) -> &'a SecretKey;
/// Gets the local secret key for blinded revocation pubkey
fn revocation_base_key<'a>(&'a self) -> &'a SecretKey;
- /// Gets the local secret key used in to_remote output of remote commitment tx
- /// (and also as part of obscured commitment number)
- fn payment_base_key<'a>(&'a self) -> &'a SecretKey;
+ /// Gets the local secret key used in the to_remote output of remote commitment tx (ie the
+ /// output to us in transactions our counterparty broadcasts).
+ /// Also as part of obscured commitment number.
+ fn payment_key<'a>(&'a self) -> &'a SecretKey;
/// Gets the local secret key used in HTLC-Success/HTLC-Timeout txn and to_local output
fn delayed_payment_base_key<'a>(&'a self) -> &'a SecretKey;
/// Gets the local htlc secret key used in commitment tx htlc outputs
/// Create a signature for a remote commitment transaction and associated HTLC transactions.
///
/// Note that if signing fails or is rejected, the channel will be force-closed.
- ///
- /// 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)!
+ //
+ // 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 + secp256k1::Verification>(&self, 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 local commitment transaction
- ///
- /// 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
- /// TODO: Ensure test-only version doesn't enforce uniqueness of signature when it's enforced in this method
- /// making the callee generate it via some util function we expose)!
- fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>);
+ /// Create a signature for a local commitment transaction. This will only ever be called with
+ /// the same local_commitment_tx (or a copy thereof), though there are currently no guarantees
+ /// that it will not be called multiple times.
+ //
+ // 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
+ fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
+
+ /// Same as sign_local_commitment, but exists only for tests to get access to local commitment
+ /// transactions which will be broadcasted later, after the channel has moved on to a newer
+ /// state. Thus, needs its own method as sign_local_commitment may enforce that we only ever
+ /// get called once.
+ #[cfg(test)]
+ fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
- /// Create a signature for a local commitment transaction without enforcing one-time signing.
+ /// Create a signature for each HTLC transaction spending a local commitment transaction.
///
- /// Testing revocation logic by our test framework needs to sign multiple local commitment
- /// transactions. This unsafe test-only version doesn't enforce one-time signing security
- /// requirement.
- #[cfg(test)]
- fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>);
+ /// Unlike sign_local_commitment, this may be called multiple times with *different*
+ /// local_commitment_tx values. While this will never be called with a revoked
+ /// local_commitment_tx, it is possible that it is called with the second-latest
+ /// local_commitment_tx (only if we haven't yet revoked it) if some watchtower/secondary
+ /// ChannelMonitor decided to broadcast before it had been updated to the latest.
+ ///
+ /// Either an Err should be returned, or a Vec with one entry for each HTLC which exists in
+ /// local_commitment_tx. For those HTLCs which have transaction_output_index set to None
+ /// (implying they were considered dust at the time the commitment transaction was negotiated),
+ /// a corresponding None should be included in the return value. All other positions in the
+ /// return value must contain a signature.
+ fn sign_local_commitment_htlc_transactions<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, local_csv: u16, secp_ctx: &Secp256k1<T>) -> Result<Vec<Option<Signature>>, ()>;
- /// Signs a transaction created by build_htlc_transaction. If the transaction is an
- /// HTLC-Success transaction, preimage must be set!
- /// TODO: should be merged with sign_local_commitment as a slice of HTLC transactions to sign
- fn sign_htlc_transaction<T: secp256k1::Signing>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, htlc_index: u32, preimage: Option<PaymentPreimage>, local_csv: u16, secp_ctx: &Secp256k1<T>);
/// Create a signature for a (proposed) closing transaction.
///
/// Note that, due to rounding, there may be one "missing" satoshi, and either party may have
funding_key: SecretKey,
/// Local secret key for blinded revocation pubkey
revocation_base_key: SecretKey,
- /// Local secret key used in commitment tx htlc outputs
- payment_base_key: SecretKey,
+ /// Local secret key used for our balance in remote-broadcasted commitment transactions
+ payment_key: SecretKey,
/// Local secret key used in HTLC tx
delayed_payment_base_key: SecretKey,
/// Local htlc secret key used in commitment tx htlc outputs
secp_ctx: &Secp256k1<C>,
funding_key: SecretKey,
revocation_base_key: SecretKey,
- payment_base_key: SecretKey,
+ payment_key: SecretKey,
delayed_payment_base_key: SecretKey,
htlc_base_key: SecretKey,
commitment_seed: [u8; 32],
channel_value_satoshis: u64) -> InMemoryChannelKeys {
let local_channel_pubkeys =
InMemoryChannelKeys::make_local_keys(secp_ctx, &funding_key, &revocation_base_key,
- &payment_base_key, &delayed_payment_base_key,
+ &payment_key, &delayed_payment_base_key,
&htlc_base_key);
InMemoryChannelKeys {
funding_key,
revocation_base_key,
- payment_base_key,
+ payment_key,
delayed_payment_base_key,
htlc_base_key,
commitment_seed,
fn make_local_keys<C: Signing>(secp_ctx: &Secp256k1<C>,
funding_key: &SecretKey,
revocation_base_key: &SecretKey,
- payment_base_key: &SecretKey,
+ payment_key: &SecretKey,
delayed_payment_base_key: &SecretKey,
htlc_base_key: &SecretKey) -> ChannelPublicKeys {
let from_secret = |s: &SecretKey| PublicKey::from_secret_key(secp_ctx, s);
ChannelPublicKeys {
funding_pubkey: from_secret(&funding_key),
revocation_basepoint: from_secret(&revocation_base_key),
- payment_basepoint: from_secret(&payment_base_key),
+ payment_point: from_secret(&payment_key),
delayed_payment_basepoint: from_secret(&delayed_payment_base_key),
htlc_basepoint: from_secret(&htlc_base_key),
}
impl ChannelKeys for InMemoryChannelKeys {
fn funding_key(&self) -> &SecretKey { &self.funding_key }
fn revocation_base_key(&self) -> &SecretKey { &self.revocation_base_key }
- fn payment_base_key(&self) -> &SecretKey { &self.payment_base_key }
+ fn payment_key(&self) -> &SecretKey { &self.payment_key }
fn delayed_payment_base_key(&self) -> &SecretKey { &self.delayed_payment_base_key }
fn htlc_base_key(&self) -> &SecretKey { &self.htlc_base_key }
fn commitment_seed(&self) -> &[u8; 32] { &self.commitment_seed }
Ok((commitment_sig, htlc_sigs))
}
- fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
- local_commitment_tx.add_local_sig(&self.funding_key, funding_redeemscript, channel_value_satoshis, secp_ctx);
+ fn sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
+ let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
+ 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);
+
+ Ok(local_commitment_tx.get_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx))
}
#[cfg(test)]
- fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
- local_commitment_tx.add_local_sig(&self.funding_key, funding_redeemscript, channel_value_satoshis, secp_ctx);
+ fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
+ let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
+ 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);
+
+ Ok(local_commitment_tx.get_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx))
}
- fn sign_htlc_transaction<T: secp256k1::Signing>(&self, local_commitment_tx: &mut LocalCommitmentTransaction, htlc_index: u32, preimage: Option<PaymentPreimage>, local_csv: u16, secp_ctx: &Secp256k1<T>) {
- local_commitment_tx.add_htlc_sig(&self.htlc_base_key, htlc_index, preimage, local_csv, secp_ctx);
+ fn sign_local_commitment_htlc_transactions<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, local_csv: u16, secp_ctx: &Secp256k1<T>) -> Result<Vec<Option<Signature>>, ()> {
+ local_commitment_tx.get_htlc_sigs(&self.htlc_base_key, local_csv, secp_ctx)
}
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
self.funding_key.write(writer)?;
self.revocation_base_key.write(writer)?;
- self.payment_base_key.write(writer)?;
+ self.payment_key.write(writer)?;
self.delayed_payment_base_key.write(writer)?;
self.htlc_base_key.write(writer)?;
self.commitment_seed.write(writer)?;
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
let funding_key = Readable::read(reader)?;
let revocation_base_key = Readable::read(reader)?;
- let payment_base_key = Readable::read(reader)?;
+ let payment_key = Readable::read(reader)?;
let delayed_payment_base_key = Readable::read(reader)?;
let htlc_base_key = Readable::read(reader)?;
let commitment_seed = Readable::read(reader)?;
let secp_ctx = Secp256k1::signing_only();
let local_channel_pubkeys =
InMemoryChannelKeys::make_local_keys(&secp_ctx, &funding_key, &revocation_base_key,
- &payment_base_key, &delayed_payment_base_key,
+ &payment_key, &delayed_payment_base_key,
&htlc_base_key);
Ok(InMemoryChannelKeys {
funding_key,
revocation_base_key,
- payment_base_key,
+ payment_key,
delayed_payment_base_key,
htlc_base_key,
commitment_seed,
let node_secret = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(0).unwrap()).expect("Your RNG is busted").private_key.key;
let destination_script = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(1).unwrap()) {
Ok(destination_key) => {
- let pubkey_hash160 = Hash160::hash(&ExtendedPubKey::from_private(&secp_ctx, &destination_key).public_key.key.serialize()[..]);
+ let wpubkey_hash = WPubkeyHash::hash(&ExtendedPubKey::from_private(&secp_ctx, &destination_key).public_key.to_bytes());
Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
- .push_slice(&pubkey_hash160.into_inner())
+ .push_slice(&wpubkey_hash.into_inner())
.into_script()
},
Err(_) => panic!("Your RNG is busted"),
}
let funding_key = key_step!(b"funding key", commitment_seed);
let revocation_base_key = key_step!(b"revocation base key", funding_key);
- let payment_base_key = key_step!(b"payment base key", revocation_base_key);
- let delayed_payment_base_key = key_step!(b"delayed payment base key", payment_base_key);
+ let payment_key = key_step!(b"payment key", revocation_base_key);
+ let delayed_payment_base_key = key_step!(b"delayed payment base key", payment_key);
let htlc_base_key = key_step!(b"HTLC base key", delayed_payment_base_key);
InMemoryChannelKeys::new(
&self.secp_ctx,
funding_key,
revocation_base_key,
- payment_base_key,
+ payment_key,
delayed_payment_base_key,
htlc_base_key,
commitment_seed,