diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 5599bfbb9fd..a4c360d330b 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -33,12 +33,13 @@ use util::ser::{Writeable, Writer, Readable}; use chain::transaction::OutPoint; use ln::chan_utils; -use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, PreCalculatedTxCreationKeys}; +use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, PreCalculatedTxCreationKeys, derive_public_key, derive_public_revocation_key, TxCreationKeys}; use ln::msgs::UnsignedChannelAnnouncement; use std::sync::atomic::{AtomicUsize, Ordering}; use std::io::Error; use ln::msgs::DecodeError; +use ln::transaction::{CommitmentInfo, build_commitment_tx, get_commitment_transaction_number_obscure_factor}; /// When on-chain outputs are created by rust-lightning (which our counterparty is not able to /// claim at any point in the future) an event is generated which you must track and be able to @@ -79,7 +80,7 @@ pub enum SpendableOutputDescriptor { /// /// To derive the revocation_pubkey provided here (which is used in the witness /// script generation), you must pass the counterparty revocation_basepoint (which appears in the - /// call to ChannelKeys::on_accept) and the provided per_commitment point + /// call to ChannelKeys::ready_channel) and the provided per_commitment point /// to chan_utils::derive_public_revocation_key. /// /// The witness script which is hashed and included in the output script_pubkey may be @@ -244,6 +245,18 @@ pub trait ChannelKeys : Send+Clone { // TODO: Add more input vars to enable better checking (preferably removing commitment_tx and fn sign_holder_commitment(&self, holder_commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1) -> Result; + /// Create a signature for a holder's commitment transaction and attached HTLC transactions. + fn sign_holder_commitment_phase2( + &self, + commitment_number: u64, + feerate_per_kw: u32, + to_holder_value_sat: u64, + to_counterparty_value_sat: u64, + htlcs: &Vec, + pre_keys: &PreCalculatedTxCreationKeys, + secp_ctx: &Secp256k1, + ) -> Result<(Signature, Vec), ()>; + /// Same as sign_holder_commitment, but exists only for tests to get access to holder commitment /// transactions which will be broadcasted later, after the channel has moved on to a newer /// state. Thus, needs its own method as sign_holder_commitment may enforce that we only ever @@ -319,13 +332,15 @@ pub trait ChannelKeys : Send+Clone { /// protocol. fn sign_channel_announcement(&self, msg: &UnsignedChannelAnnouncement, secp_ctx: &Secp256k1) -> Result; - /// Set the counterparty channel basepoints and counterparty_selected/holder_selected_contest_delay. - /// This is done immediately on incoming channels and as soon as the channel is accepted on outgoing channels. + /// Set the counterparty static channel data, including basepoints, + /// counterparty_selected/holder_selected_contest_delay and funding outpoint. + /// This is done as soon as the funding outpoint is known. Since these are static channel data, + /// they MUST NOT be allowed to change to different values once set. /// /// We bind holder_selected_contest_delay late here for API convenience. /// /// Will be called before any signatures are applied. - fn on_accept(&mut self, channel_points: &ChannelPublicKeys, counterparty_selected_contest_delay: u16, holder_selected_contest_delay: u16); + fn ready_channel(&mut self, channel_points: &ChannelPublicKeys, counterparty_selected_contest_delay: u16, holder_selected_contest_delay: u16, is_outbound: bool, funding_outpoint: &OutPoint); } /// A trait to describe an object which can get user secrets and key material. @@ -349,11 +364,11 @@ pub trait KeysInterface: Send + Sync { } #[derive(Clone)] -/// Holds late-bound channel data. -/// This data is available after the channel is known to be accepted, either -/// when receiving an open_channel for an inbound channel or when -/// receiving accept_channel for an outbound channel. -struct AcceptedChannelData { +/// Holds late-bound static channel data. +/// This data is available after the channel is readied, either +/// when receiving an funding_created for an inbound channel or when +/// creating a funding transaction for an outbound channel. +struct StaticChannelData { /// Counterparty public keys and base points counterparty_channel_pubkeys: ChannelPublicKeys, /// The contest_delay value specified by our counterparty and applied on holder-broadcastable @@ -365,6 +380,8 @@ struct AcceptedChannelData { /// by our counterparty, ie the amount of time that they have to wait to recover their funds /// if they broadcast a transaction. holder_selected_contest_delay: u16, + /// Whether the holder is the initiator of this channel + is_outbound: bool, } #[derive(Clone)] @@ -385,7 +402,9 @@ pub struct InMemoryChannelKeys { /// Holder public keys and basepoints pub(crate) holder_channel_pubkeys: ChannelPublicKeys, /// Counterparty public keys and counterparty/holder selected_contest_delay, populated on channel acceptance - accepted_channel_data: Option, + accepted_channel_data: Option, + /// Funding outpoint, populated on channel funding creation + funding_outpoint: Option, /// The total value of this channel channel_value_satoshis: u64, /// Key derivation parameters @@ -418,6 +437,7 @@ impl InMemoryChannelKeys { channel_value_satoshis, holder_channel_pubkeys, accepted_channel_data: None, + funding_outpoint: None, key_derivation_params, } } @@ -439,21 +459,83 @@ impl InMemoryChannelKeys { } /// Counterparty pubkeys. - /// Will panic if on_accept wasn't called. + /// Will panic if ready_channel wasn't called. pub fn counterparty_pubkeys(&self) -> &ChannelPublicKeys { &self.accepted_channel_data.as_ref().unwrap().counterparty_channel_pubkeys } /// The contest_delay value specified by our counterparty and applied on holder-broadcastable /// transactions, ie the amount of time that we have to wait to recover our funds if we /// broadcast a transaction. You'll likely want to pass this to the /// ln::chan_utils::build*_transaction functions when signing holder's transactions. - /// Will panic if on_accept wasn't called. + /// Will panic if ready_channel wasn't called. pub fn counterparty_selected_contest_delay(&self) -> u16 { self.accepted_channel_data.as_ref().unwrap().counterparty_selected_contest_delay } /// The contest_delay value specified by us and applied on transactions broadcastable /// by our counterparty, ie the amount of time that they have to wait to recover their funds /// if they broadcast a transaction. - /// Will panic if on_accept wasn't called. + /// Will panic if ready_channel wasn't called. pub fn holder_selected_contest_delay(&self) -> u16 { self.accepted_channel_data.as_ref().unwrap().holder_selected_contest_delay } + + /// Whether the holder is the initiator + pub fn is_outbound(&self) -> bool { self.accepted_channel_data.as_ref().unwrap().is_outbound } + + /// Funding outpoint + /// Will panic if ready_channel wasn't called. + pub fn funding_outpoint(&self) -> &OutPoint { self.funding_outpoint.as_ref().unwrap() } + + /// Prepare build information for a commitment tx that the holder can broadcast + pub fn build_holder_commitment_tx( + &self, + commitment_number: u64, + per_commitment_point: &PublicKey, + to_holder_value_sat: u64, + to_counterparty_value_sat: u64, + htlcs: &Vec, + keys: &TxCreationKeys, + secp_ctx: &Secp256k1, + ) -> Result<(bitcoin::Transaction, Vec, Vec