use util::ser::{Writeable, Writer, Readable};
use ln::chan_utils;
-use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys};
+use ln::chan_utils::{TxCreationKeys, HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, LocalCommitmentTransaction};
+use ln::channelmanager::PaymentPreimage;
use ln::msgs;
use std::sync::Arc;
/// spend on-chain. The information needed to do this is provided in this enum, including the
/// outpoint describing which txid and output index is available, the full output which exists at
/// that txid/index, and any keys or other information required to sign.
+#[derive(Clone, PartialEq)]
pub enum SpendableOutputDescriptor {
/// An output to a script which was provided via KeysInterface, thus you should already know
/// how to spend it. No keys are provided as rust-lightning was never given any keys - only the
/// The private key which should be used to sign the transaction is provided, as well as the
/// full witness redeemScript which is hashed in the output script_pubkey.
/// The witness in the spending input should be:
- /// <BIP 143 signature generated with the given key> <one zero byte aka OP_0>
+ /// <BIP 143 signature generated with the given key> <empty vector> (MINIMALIF standard rule)
/// <witness_script as provided>
/// Note that the nSequence field in the input must be set to_self_delay (which corresponds to
/// the transaction not being broadcastable until at least to_self_delay blocks after the input
}
}
+impl Writeable for SpendableOutputDescriptor {
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+ match self {
+ &SpendableOutputDescriptor::StaticOutput { ref outpoint, ref output } => {
+ 0u8.write(writer)?;
+ outpoint.write(writer)?;
+ output.write(writer)?;
+ },
+ &SpendableOutputDescriptor::DynamicOutputP2WSH { ref outpoint, ref key, ref witness_script, ref to_self_delay, ref output } => {
+ 1u8.write(writer)?;
+ outpoint.write(writer)?;
+ key.write(writer)?;
+ witness_script.write(writer)?;
+ to_self_delay.write(writer)?;
+ output.write(writer)?;
+ },
+ &SpendableOutputDescriptor::DynamicOutputP2WPKH { ref outpoint, ref key, ref output } => {
+ 2u8.write(writer)?;
+ outpoint.write(writer)?;
+ key.write(writer)?;
+ output.write(writer)?;
+ },
+ }
+ Ok(())
+ }
+}
+
+impl Readable for SpendableOutputDescriptor {
+ fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ match Readable::read(reader)? {
+ 0u8 => Ok(SpendableOutputDescriptor::StaticOutput {
+ outpoint: Readable::read(reader)?,
+ output: Readable::read(reader)?,
+ }),
+ 1u8 => Ok(SpendableOutputDescriptor::DynamicOutputP2WSH {
+ outpoint: Readable::read(reader)?,
+ key: Readable::read(reader)?,
+ witness_script: Readable::read(reader)?,
+ to_self_delay: Readable::read(reader)?,
+ output: Readable::read(reader)?,
+ }),
+ 2u8 => Ok(SpendableOutputDescriptor::DynamicOutputP2WPKH {
+ outpoint: Readable::read(reader)?,
+ key: Readable::read(reader)?,
+ output: Readable::read(reader)?,
+ }),
+ _ => Err(DecodeError::InvalidValue),
+ }
+ }
+}
+
/// A trait to describe an object which can get user secrets and key material.
pub trait KeysInterface: Send + Sync {
/// A type which implements ChannelKeys which will be returned by get_channel_keys.
/// (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: remove Clone once we start returning ChannelUpdate objects instead of copying ChannelMonitor
+/// 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;
/// 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 without enforcing one-time signing.
+ ///
+ /// 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>);
+
+ /// 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
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);
+ }
+
+ #[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 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_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
if closing_tx.input.len() != 1 { return Err(()); }
if closing_tx.input[0].witness.len() != 0 { return Err(()); }
}
}
-impl<R: ::std::io::Read> Readable<R> for InMemoryChannelKeys {
- fn read(reader: &mut R) -> Result<Self, DecodeError> {
+impl Readable for InMemoryChannelKeys {
+ 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)?;