2020-08-10 15:00:09 -04:00
|
|
|
// This file is Copyright its original authors, visible in version control
|
|
|
|
// history.
|
|
|
|
//
|
|
|
|
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
|
|
|
|
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
|
|
|
|
// You may not use this file except in accordance with one or both of these
|
|
|
|
// licenses.
|
|
|
|
|
2020-09-06 20:07:11 -04:00
|
|
|
use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, ChannelPublicKeys, HolderCommitmentTransaction, PreCalculatedTxCreationKeys};
|
Batch-sign local HTLC txn with a well-doc'd API, returning sigs
1107ab06c33bd360bdee7ee64f4b690e753003f6 introduced an API to have a
ChannelKeys implementer sign HTLC transactions by calling into the
LocalCommitmentTransaction object, which would then store the tx.
This API was incredibly awkward, both because it required an
external signer trust our own internal interfaces, but also because
it didn't allow for any inspection of what was about to be signed.
Further, it signed the HTLC transactions one-by-one in a somewhat
inefficient way, and there isn't a clear way to resolve this (as
the which-HTLC parameter has to refer to something in between the
HTLC's arbitrary index, and its index in the commitment tx, which
has "holes" for the non-HTLC outputs and skips some HTLCs).
We replace it with a new function in ChannelKeys which allows us
to sign all HTLCs in a given commitment transaction (which allows
for a bit more effeciency on the signers' part, as well as
sidesteps the which-HTLC issue). This may also simplify the signer
implementation as we will always want to sign all HTLCs spending a
given commitment transaction at once anyway.
We also de-mut the LocalCommitmentTransaction passed to the
ChanKeys, instead opting to make LocalCommitmentTransaction const
and avoid storing any new HTLC-related data in it.
2020-04-19 22:59:53 -04:00
|
|
|
use ln::{chan_utils, msgs};
|
2019-11-26 16:46:33 -05:00
|
|
|
use chain::keysinterface::{ChannelKeys, InMemoryChannelKeys};
|
|
|
|
|
2019-11-27 16:08:48 -05:00
|
|
|
use std::cmp;
|
2020-02-04 09:15:59 -08:00
|
|
|
use std::sync::{Mutex, Arc};
|
2019-11-27 16:08:48 -05:00
|
|
|
|
2020-08-25 18:47:24 -04:00
|
|
|
use bitcoin::blockdata::transaction::{Transaction, SigHashType};
|
Batch-sign local HTLC txn with a well-doc'd API, returning sigs
1107ab06c33bd360bdee7ee64f4b690e753003f6 introduced an API to have a
ChannelKeys implementer sign HTLC transactions by calling into the
LocalCommitmentTransaction object, which would then store the tx.
This API was incredibly awkward, both because it required an
external signer trust our own internal interfaces, but also because
it didn't allow for any inspection of what was about to be signed.
Further, it signed the HTLC transactions one-by-one in a somewhat
inefficient way, and there isn't a clear way to resolve this (as
the which-HTLC parameter has to refer to something in between the
HTLC's arbitrary index, and its index in the commitment tx, which
has "holes" for the non-HTLC outputs and skips some HTLCs).
We replace it with a new function in ChannelKeys which allows us
to sign all HTLCs in a given commitment transaction (which allows
for a bit more effeciency on the signers' part, as well as
sidesteps the which-HTLC issue). This may also simplify the signer
implementation as we will always want to sign all HTLCs spending a
given commitment transaction at once anyway.
We also de-mut the LocalCommitmentTransaction passed to the
ChanKeys, instead opting to make LocalCommitmentTransaction const
and avoid storing any new HTLC-related data in it.
2020-04-19 22:59:53 -04:00
|
|
|
use bitcoin::util::bip143;
|
2019-11-27 16:08:48 -05:00
|
|
|
|
2020-04-27 16:51:59 +02:00
|
|
|
use bitcoin::secp256k1;
|
|
|
|
use bitcoin::secp256k1::key::{SecretKey, PublicKey};
|
|
|
|
use bitcoin::secp256k1::{Secp256k1, Signature};
|
2020-02-04 09:15:59 -08:00
|
|
|
use util::ser::{Writeable, Writer, Readable};
|
|
|
|
use std::io::Error;
|
|
|
|
use ln::msgs::DecodeError;
|
2019-11-26 16:46:33 -05:00
|
|
|
|
|
|
|
/// Enforces some rules on ChannelKeys calls. Eventually we will probably want to expose a variant
|
|
|
|
/// of this which would essentially be what you'd want to run on a hardware wallet.
|
2020-02-04 09:15:59 -08:00
|
|
|
#[derive(Clone)]
|
2019-11-26 16:46:33 -05:00
|
|
|
pub struct EnforcingChannelKeys {
|
|
|
|
pub inner: InMemoryChannelKeys,
|
2020-02-04 09:15:59 -08:00
|
|
|
commitment_number_obscure_and_last: Arc<Mutex<(Option<u64>, u64)>>,
|
2019-11-26 16:46:33 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl EnforcingChannelKeys {
|
|
|
|
pub fn new(inner: InMemoryChannelKeys) -> Self {
|
|
|
|
Self {
|
|
|
|
inner,
|
2020-02-04 09:15:59 -08:00
|
|
|
commitment_number_obscure_and_last: Arc::new(Mutex::new((None, 0))),
|
2019-11-26 16:46:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-16 16:51:15 -08:00
|
|
|
|
|
|
|
impl EnforcingChannelKeys {
|
|
|
|
fn check_keys<T: secp256k1::Signing + secp256k1::Verification>(&self, secp_ctx: &Secp256k1<T>,
|
|
|
|
keys: &TxCreationKeys) {
|
2020-08-26 15:27:12 -04:00
|
|
|
let remote_points = self.inner.counterparty_pubkeys();
|
2020-01-16 16:51:15 -08:00
|
|
|
|
2020-08-13 14:45:34 -04:00
|
|
|
let keys_expected = TxCreationKeys::derive_new(secp_ctx,
|
|
|
|
&keys.per_commitment_point,
|
|
|
|
&remote_points.delayed_payment_basepoint,
|
|
|
|
&remote_points.htlc_basepoint,
|
|
|
|
&self.inner.pubkeys().revocation_basepoint,
|
|
|
|
&self.inner.pubkeys().htlc_basepoint).unwrap();
|
2020-01-16 16:51:15 -08:00
|
|
|
if keys != &keys_expected { panic!("derived different per-tx keys") }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-26 16:46:33 -05:00
|
|
|
impl ChannelKeys for EnforcingChannelKeys {
|
2020-07-11 03:19:43 -07:00
|
|
|
fn get_per_commitment_point<T: secp256k1::Signing + secp256k1::Verification>(&self, idx: u64, secp_ctx: &Secp256k1<T>) -> PublicKey {
|
|
|
|
self.inner.get_per_commitment_point(idx, secp_ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn release_commitment_secret(&self, idx: u64) -> [u8; 32] {
|
|
|
|
// TODO: enforce the ChannelKeys contract - error here if we already signed this commitment
|
|
|
|
self.inner.release_commitment_secret(idx)
|
|
|
|
}
|
|
|
|
|
2020-05-30 23:18:35 -04:00
|
|
|
fn pubkeys(&self) -> &ChannelPublicKeys { self.inner.pubkeys() }
|
2020-05-05 20:00:01 -04:00
|
|
|
fn key_derivation_params(&self) -> (u64, u64) { self.inner.key_derivation_params() }
|
2019-11-27 16:08:48 -05:00
|
|
|
|
2020-08-31 15:31:19 -04:00
|
|
|
fn sign_counterparty_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, feerate_per_kw: u32, commitment_tx: &Transaction, pre_keys: &PreCalculatedTxCreationKeys, htlcs: &[&HTLCOutputInCommitment], secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()> {
|
2020-01-16 16:51:15 -08:00
|
|
|
if commitment_tx.input.len() != 1 { panic!("lightning commitment transactions have a single input"); }
|
2020-08-09 15:45:23 +02:00
|
|
|
self.check_keys(secp_ctx, pre_keys.trust_key_derivation());
|
2019-11-27 16:08:48 -05:00
|
|
|
let obscured_commitment_transaction_number = (commitment_tx.lock_time & 0xffffff) as u64 | ((commitment_tx.input[0].sequence as u64 & 0xffffff) << 3*8);
|
|
|
|
|
|
|
|
{
|
|
|
|
let mut commitment_data = self.commitment_number_obscure_and_last.lock().unwrap();
|
|
|
|
if commitment_data.0.is_none() {
|
|
|
|
commitment_data.0 = Some(obscured_commitment_transaction_number ^ commitment_data.1);
|
|
|
|
}
|
|
|
|
let commitment_number = obscured_commitment_transaction_number ^ commitment_data.0.unwrap();
|
|
|
|
assert!(commitment_number == commitment_data.1 || commitment_number == commitment_data.1 + 1);
|
|
|
|
commitment_data.1 = cmp::max(commitment_number, commitment_data.1)
|
|
|
|
}
|
|
|
|
|
2020-08-31 15:31:19 -04:00
|
|
|
Ok(self.inner.sign_counterparty_commitment(feerate_per_kw, commitment_tx, pre_keys, htlcs, secp_ctx).unwrap())
|
2019-11-27 16:08:48 -05:00
|
|
|
}
|
2019-12-07 17:54:55 -05:00
|
|
|
|
2020-09-06 20:07:11 -04:00
|
|
|
fn sign_holder_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, holder_commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
|
2020-07-11 03:19:43 -07:00
|
|
|
// TODO: enforce the ChannelKeys contract - error if this commitment was already revoked
|
|
|
|
// TODO: need the commitment number
|
2020-08-31 15:31:19 -04:00
|
|
|
Ok(self.inner.sign_holder_commitment(holder_commitment_tx, secp_ctx).unwrap())
|
2020-03-20 18:04:01 -04:00
|
|
|
}
|
|
|
|
|
2020-07-03 13:41:21 -07:00
|
|
|
#[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
|
2020-09-06 20:07:11 -04:00
|
|
|
fn unsafe_sign_holder_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, holder_commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
|
2020-08-31 15:31:19 -04:00
|
|
|
Ok(self.inner.unsafe_sign_holder_commitment(holder_commitment_tx, secp_ctx).unwrap())
|
2020-03-20 18:04:01 -04:00
|
|
|
}
|
|
|
|
|
2020-09-06 20:07:11 -04:00
|
|
|
fn sign_holder_commitment_htlc_transactions<T: secp256k1::Signing + secp256k1::Verification>(&self, holder_commitment_tx: &HolderCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Vec<Option<Signature>>, ()> {
|
2020-08-31 15:31:19 -04:00
|
|
|
let commitment_txid = holder_commitment_tx.txid();
|
2020-09-06 20:07:11 -04:00
|
|
|
let holder_csv = self.inner.counterparty_selected_contest_delay();
|
Batch-sign local HTLC txn with a well-doc'd API, returning sigs
1107ab06c33bd360bdee7ee64f4b690e753003f6 introduced an API to have a
ChannelKeys implementer sign HTLC transactions by calling into the
LocalCommitmentTransaction object, which would then store the tx.
This API was incredibly awkward, both because it required an
external signer trust our own internal interfaces, but also because
it didn't allow for any inspection of what was about to be signed.
Further, it signed the HTLC transactions one-by-one in a somewhat
inefficient way, and there isn't a clear way to resolve this (as
the which-HTLC parameter has to refer to something in between the
HTLC's arbitrary index, and its index in the commitment tx, which
has "holes" for the non-HTLC outputs and skips some HTLCs).
We replace it with a new function in ChannelKeys which allows us
to sign all HTLCs in a given commitment transaction (which allows
for a bit more effeciency on the signers' part, as well as
sidesteps the which-HTLC issue). This may also simplify the signer
implementation as we will always want to sign all HTLCs spending a
given commitment transaction at once anyway.
We also de-mut the LocalCommitmentTransaction passed to the
ChanKeys, instead opting to make LocalCommitmentTransaction const
and avoid storing any new HTLC-related data in it.
2020-04-19 22:59:53 -04:00
|
|
|
|
2020-08-31 15:31:19 -04:00
|
|
|
for this_htlc in holder_commitment_tx.per_htlc.iter() {
|
Batch-sign local HTLC txn with a well-doc'd API, returning sigs
1107ab06c33bd360bdee7ee64f4b690e753003f6 introduced an API to have a
ChannelKeys implementer sign HTLC transactions by calling into the
LocalCommitmentTransaction object, which would then store the tx.
This API was incredibly awkward, both because it required an
external signer trust our own internal interfaces, but also because
it didn't allow for any inspection of what was about to be signed.
Further, it signed the HTLC transactions one-by-one in a somewhat
inefficient way, and there isn't a clear way to resolve this (as
the which-HTLC parameter has to refer to something in between the
HTLC's arbitrary index, and its index in the commitment tx, which
has "holes" for the non-HTLC outputs and skips some HTLCs).
We replace it with a new function in ChannelKeys which allows us
to sign all HTLCs in a given commitment transaction (which allows
for a bit more effeciency on the signers' part, as well as
sidesteps the which-HTLC issue). This may also simplify the signer
implementation as we will always want to sign all HTLCs spending a
given commitment transaction at once anyway.
We also de-mut the LocalCommitmentTransaction passed to the
ChanKeys, instead opting to make LocalCommitmentTransaction const
and avoid storing any new HTLC-related data in it.
2020-04-19 22:59:53 -04:00
|
|
|
if this_htlc.0.transaction_output_index.is_some() {
|
2020-09-06 20:07:11 -04:00
|
|
|
let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, holder_commitment_tx.feerate_per_kw, holder_csv, &this_htlc.0, &holder_commitment_tx.keys.broadcaster_delayed_payment_key, &holder_commitment_tx.keys.revocation_key);
|
Batch-sign local HTLC txn with a well-doc'd API, returning sigs
1107ab06c33bd360bdee7ee64f4b690e753003f6 introduced an API to have a
ChannelKeys implementer sign HTLC transactions by calling into the
LocalCommitmentTransaction object, which would then store the tx.
This API was incredibly awkward, both because it required an
external signer trust our own internal interfaces, but also because
it didn't allow for any inspection of what was about to be signed.
Further, it signed the HTLC transactions one-by-one in a somewhat
inefficient way, and there isn't a clear way to resolve this (as
the which-HTLC parameter has to refer to something in between the
HTLC's arbitrary index, and its index in the commitment tx, which
has "holes" for the non-HTLC outputs and skips some HTLCs).
We replace it with a new function in ChannelKeys which allows us
to sign all HTLCs in a given commitment transaction (which allows
for a bit more effeciency on the signers' part, as well as
sidesteps the which-HTLC issue). This may also simplify the signer
implementation as we will always want to sign all HTLCs spending a
given commitment transaction at once anyway.
We also de-mut the LocalCommitmentTransaction passed to the
ChanKeys, instead opting to make LocalCommitmentTransaction const
and avoid storing any new HTLC-related data in it.
2020-04-19 22:59:53 -04:00
|
|
|
|
2020-09-06 20:07:11 -04:00
|
|
|
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&this_htlc.0, &holder_commitment_tx.keys);
|
Batch-sign local HTLC txn with a well-doc'd API, returning sigs
1107ab06c33bd360bdee7ee64f4b690e753003f6 introduced an API to have a
ChannelKeys implementer sign HTLC transactions by calling into the
LocalCommitmentTransaction object, which would then store the tx.
This API was incredibly awkward, both because it required an
external signer trust our own internal interfaces, but also because
it didn't allow for any inspection of what was about to be signed.
Further, it signed the HTLC transactions one-by-one in a somewhat
inefficient way, and there isn't a clear way to resolve this (as
the which-HTLC parameter has to refer to something in between the
HTLC's arbitrary index, and its index in the commitment tx, which
has "holes" for the non-HTLC outputs and skips some HTLCs).
We replace it with a new function in ChannelKeys which allows us
to sign all HTLCs in a given commitment transaction (which allows
for a bit more effeciency on the signers' part, as well as
sidesteps the which-HTLC issue). This may also simplify the signer
implementation as we will always want to sign all HTLCs spending a
given commitment transaction at once anyway.
We also de-mut the LocalCommitmentTransaction passed to the
ChanKeys, instead opting to make LocalCommitmentTransaction const
and avoid storing any new HTLC-related data in it.
2020-04-19 22:59:53 -04:00
|
|
|
|
2020-08-25 18:47:24 -04:00
|
|
|
let sighash = hash_to_message!(&bip143::SigHashCache::new(&htlc_tx).signature_hash(0, &htlc_redeemscript, this_htlc.0.amount_msat / 1000, SigHashType::All)[..]);
|
2020-09-06 20:07:11 -04:00
|
|
|
secp_ctx.verify(&sighash, this_htlc.1.as_ref().unwrap(), &holder_commitment_tx.keys.countersignatory_htlc_key).unwrap();
|
Batch-sign local HTLC txn with a well-doc'd API, returning sigs
1107ab06c33bd360bdee7ee64f4b690e753003f6 introduced an API to have a
ChannelKeys implementer sign HTLC transactions by calling into the
LocalCommitmentTransaction object, which would then store the tx.
This API was incredibly awkward, both because it required an
external signer trust our own internal interfaces, but also because
it didn't allow for any inspection of what was about to be signed.
Further, it signed the HTLC transactions one-by-one in a somewhat
inefficient way, and there isn't a clear way to resolve this (as
the which-HTLC parameter has to refer to something in between the
HTLC's arbitrary index, and its index in the commitment tx, which
has "holes" for the non-HTLC outputs and skips some HTLCs).
We replace it with a new function in ChannelKeys which allows us
to sign all HTLCs in a given commitment transaction (which allows
for a bit more effeciency on the signers' part, as well as
sidesteps the which-HTLC issue). This may also simplify the signer
implementation as we will always want to sign all HTLCs spending a
given commitment transaction at once anyway.
We also de-mut the LocalCommitmentTransaction passed to the
ChanKeys, instead opting to make LocalCommitmentTransaction const
and avoid storing any new HTLC-related data in it.
2020-04-19 22:59:53 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-31 15:31:19 -04:00
|
|
|
Ok(self.inner.sign_holder_commitment_htlc_transactions(holder_commitment_tx, secp_ctx).unwrap())
|
2020-03-21 15:39:19 -04:00
|
|
|
}
|
|
|
|
|
2020-07-23 06:54:49 -07:00
|
|
|
fn sign_justice_transaction<T: secp256k1::Signing + secp256k1::Verification>(&self, justice_tx: &Transaction, input: usize, amount: u64, per_commitment_key: &SecretKey, htlc: &Option<HTLCOutputInCommitment>, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
|
|
|
|
Ok(self.inner.sign_justice_transaction(justice_tx, input, amount, per_commitment_key, htlc, secp_ctx).unwrap())
|
2020-03-24 14:22:16 -04:00
|
|
|
}
|
|
|
|
|
2020-08-31 15:31:19 -04:00
|
|
|
fn sign_counterparty_htlc_transaction<T: secp256k1::Signing + secp256k1::Verification>(&self, htlc_tx: &Transaction, input: usize, amount: u64, per_commitment_point: &PublicKey, htlc: &HTLCOutputInCommitment, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
|
|
|
|
Ok(self.inner.sign_counterparty_htlc_transaction(htlc_tx, input, amount, per_commitment_point, htlc, secp_ctx).unwrap())
|
2020-03-24 15:04:36 -04:00
|
|
|
}
|
|
|
|
|
2020-01-23 14:32:29 -08:00
|
|
|
fn sign_closing_transaction<T: secp256k1::Signing>(&self, closing_tx: &Transaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
|
|
|
|
Ok(self.inner.sign_closing_transaction(closing_tx, secp_ctx).unwrap())
|
2019-12-13 01:57:45 -05:00
|
|
|
}
|
|
|
|
|
2019-12-07 17:54:55 -05:00
|
|
|
fn sign_channel_announcement<T: secp256k1::Signing>(&self, msg: &msgs::UnsignedChannelAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
|
|
|
|
self.inner.sign_channel_announcement(msg, secp_ctx)
|
|
|
|
}
|
2020-01-09 17:28:48 -08:00
|
|
|
|
2020-08-26 15:27:12 -04:00
|
|
|
fn on_accept(&mut self, channel_pubkeys: &ChannelPublicKeys, remote_locally_selected_delay: u16, locally_selected_delay: u16) {
|
|
|
|
self.inner.on_accept(channel_pubkeys, remote_locally_selected_delay, locally_selected_delay)
|
2020-01-09 17:28:48 -08:00
|
|
|
}
|
2019-11-26 16:46:33 -05:00
|
|
|
}
|
|
|
|
|
2020-02-04 09:15:59 -08:00
|
|
|
impl Writeable for EnforcingChannelKeys {
|
|
|
|
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), Error> {
|
|
|
|
self.inner.write(writer)?;
|
|
|
|
let (obscure, last) = *self.commitment_number_obscure_and_last.lock().unwrap();
|
|
|
|
obscure.write(writer)?;
|
|
|
|
last.write(writer)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
2020-01-16 16:51:15 -08:00
|
|
|
|
2020-02-23 23:12:19 -05:00
|
|
|
impl Readable for EnforcingChannelKeys {
|
|
|
|
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
|
2020-02-04 09:15:59 -08:00
|
|
|
let inner = Readable::read(reader)?;
|
|
|
|
let obscure_and_last = Readable::read(reader)?;
|
|
|
|
Ok(EnforcingChannelKeys {
|
|
|
|
inner: inner,
|
|
|
|
commitment_number_obscure_and_last: Arc::new(Mutex::new(obscure_and_last))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|