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-10-15 13:45:18 +02:00
use ln ::chan_utils ::{ HTLCOutputInCommitment , ChannelPublicKeys , HolderCommitmentTransaction , CommitmentTransaction , ChannelTransactionParameters , TrustedCommitmentTransaction } ;
2021-01-05 14:13:05 -08:00
use ln ::{ chan_utils , msgs } ;
2021-04-01 12:24:21 +02:00
use chain ::keysinterface ::{ Sign , InMemorySigner , BaseSign } ;
2019-11-26 16:46:33 -05:00
2021-08-01 18:22:06 +02:00
use io ;
2021-05-19 04:21:39 +00:00
use prelude ::* ;
2021-05-23 23:22:46 +00:00
use core ::cmp ;
2021-07-19 15:01:58 +02:00
use 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 } ;
2021-08-01 18:22:06 +02:00
use io ::Error ;
2020-02-04 09:15:59 -08:00
use ln ::msgs ::DecodeError ;
2019-11-26 16:46:33 -05:00
2020-07-12 09:00:10 -07:00
/// Initial value for revoked commitment downward counter
pub const INITIAL_REVOKED_COMMITMENT_NUMBER : u64 = 1 < < 48 ;
2021-02-16 16:30:08 -05:00
/// An implementation of Sign that enforces some policy checks. The current checks
2021-01-13 17:36:07 -08:00
/// are an incomplete set. They include:
///
/// - When signing, the holder transaction has not been revoked
/// - When revoking, the holder transaction has not been signed
/// - The holder commitment number is monotonic and without gaps
/// - The counterparty commitment number is monotonic and without gaps
/// - The pre-derived keys and pre-built transaction in CommitmentTransaction were correctly built
2020-10-15 13:45:18 +02:00
///
/// 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.
2021-05-07 22:36:45 +00:00
///
/// Note that before we do so we should ensure its serialization format has backwards- and
/// forwards-compatibility prefix/suffixes!
2020-02-04 09:15:59 -08:00
#[ derive(Clone) ]
2021-02-16 16:30:08 -05:00
pub struct EnforcingSigner {
pub inner : InMemorySigner ,
2021-01-13 17:36:07 -08:00
/// The last counterparty commitment number we signed, backwards counting
2020-12-05 18:56:27 +01:00
pub last_commitment_number : Arc < Mutex < Option < u64 > > > ,
2021-01-13 17:36:07 -08:00
/// The last holder commitment number we revoked, backwards counting
2020-12-05 18:56:27 +01:00
pub revoked_commitment : Arc < Mutex < u64 > > ,
2021-01-13 17:36:07 -08:00
pub disable_revocation_policy_check : bool ,
2019-11-26 16:46:33 -05:00
}
2021-02-16 16:30:08 -05:00
impl EnforcingSigner {
/// Construct an EnforcingSigner
pub fn new ( inner : InMemorySigner ) -> Self {
2019-11-26 16:46:33 -05:00
Self {
inner ,
2020-10-15 13:45:18 +02:00
last_commitment_number : Arc ::new ( Mutex ::new ( None ) ) ,
2021-01-13 17:36:07 -08:00
revoked_commitment : Arc ::new ( Mutex ::new ( INITIAL_REVOKED_COMMITMENT_NUMBER ) ) ,
disable_revocation_policy_check : false
2020-07-12 09:00:10 -07:00
}
}
2021-02-16 16:30:08 -05:00
/// Construct an EnforcingSigner with externally managed storage
2021-01-13 17:36:07 -08:00
///
/// Since there are multiple copies of this struct for each channel, some coordination is needed
/// so that all copies are aware of revocations. A pointer to this state is provided here, usually
/// by an implementation of KeysInterface.
2021-02-16 16:30:08 -05:00
pub fn new_with_revoked ( inner : InMemorySigner , revoked_commitment : Arc < Mutex < u64 > > , disable_revocation_policy_check : bool ) -> Self {
2020-07-12 09:00:10 -07:00
Self {
inner ,
last_commitment_number : Arc ::new ( Mutex ::new ( None ) ) ,
2021-01-13 17:36:07 -08:00
revoked_commitment ,
disable_revocation_policy_check
2019-11-26 16:46:33 -05:00
}
}
}
2020-01-16 16:51:15 -08:00
2021-04-01 12:24:21 +02:00
impl BaseSign for EnforcingSigner {
2021-04-01 12:40:35 +02:00
fn get_per_commitment_point ( & self , idx : u64 , secp_ctx : & Secp256k1 < secp256k1 ::All > ) -> PublicKey {
2020-07-11 03:19:43 -07:00
self . inner . get_per_commitment_point ( idx , secp_ctx )
}
fn release_commitment_secret ( & self , idx : u64 ) -> [ u8 ; 32 ] {
2020-07-12 09:00:10 -07:00
{
let mut revoked = self . revoked_commitment . lock ( ) . unwrap ( ) ;
assert! ( idx = = * revoked | | idx = = * revoked - 1 , " can only revoke the current or next unrevoked commitment - trying {}, revoked {} " , idx , * revoked ) ;
* revoked = idx ;
}
2020-07-11 03:19:43 -07:00
self . inner . release_commitment_secret ( idx )
}
2020-05-30 23:18:35 -04:00
fn pubkeys ( & self ) -> & ChannelPublicKeys { self . inner . pubkeys ( ) }
2021-02-06 13:11:23 -05:00
fn channel_keys_id ( & self ) -> [ u8 ; 32 ] { self . inner . channel_keys_id ( ) }
2019-11-27 16:08:48 -05:00
2021-04-01 12:40:35 +02:00
fn sign_counterparty_commitment ( & self , commitment_tx : & CommitmentTransaction , secp_ctx : & Secp256k1 < secp256k1 ::All > ) -> Result < ( Signature , Vec < Signature > ) , ( ) > {
2020-10-15 13:45:18 +02:00
self . verify_counterparty_commitment_tx ( commitment_tx , secp_ctx ) ;
2019-11-27 16:08:48 -05:00
{
2020-10-15 13:45:18 +02:00
let mut last_commitment_number_guard = self . last_commitment_number . lock ( ) . unwrap ( ) ;
let actual_commitment_number = commitment_tx . commitment_number ( ) ;
let last_commitment_number = last_commitment_number_guard . unwrap_or ( actual_commitment_number ) ;
// These commitment numbers are backwards counting. We expect either the same as the previously encountered,
// or the next one.
assert! ( last_commitment_number = = actual_commitment_number | | last_commitment_number - 1 = = actual_commitment_number , " {} doesn't come after {} " , actual_commitment_number , last_commitment_number ) ;
* last_commitment_number_guard = Some ( cmp ::min ( last_commitment_number , actual_commitment_number ) )
2019-11-27 16:08:48 -05:00
}
2020-10-15 13:45:18 +02:00
Ok ( self . inner . sign_counterparty_commitment ( commitment_tx , secp_ctx ) . unwrap ( ) )
2019-11-27 16:08:48 -05:00
}
2019-12-07 17:54:55 -05:00
2021-04-01 12:40:35 +02:00
fn sign_holder_commitment_and_htlcs ( & self , commitment_tx : & HolderCommitmentTransaction , secp_ctx : & Secp256k1 < secp256k1 ::All > ) -> Result < ( Signature , Vec < Signature > ) , ( ) > {
2020-10-15 13:45:18 +02:00
let trusted_tx = self . verify_holder_commitment_tx ( commitment_tx , secp_ctx ) ;
let commitment_txid = trusted_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-07-12 09:00:10 -07:00
let revoked = self . revoked_commitment . lock ( ) . unwrap ( ) ;
let commitment_number = trusted_tx . commitment_number ( ) ;
if * revoked - 1 ! = commitment_number & & * revoked - 2 ! = commitment_number {
2021-01-13 17:36:07 -08:00
if ! self . disable_revocation_policy_check {
panic! ( " can only sign the next two unrevoked commitment numbers, revoked= {} vs requested= {} for {} " ,
* revoked , commitment_number , self . inner . commitment_seed [ 0 ] )
}
2020-07-12 09:00:10 -07:00
}
2020-10-15 13:45:18 +02:00
for ( this_htlc , sig ) in trusted_tx . htlcs ( ) . iter ( ) . zip ( & commitment_tx . counterparty_htlc_sigs ) {
assert! ( this_htlc . transaction_output_index . is_some ( ) ) ;
let keys = trusted_tx . keys ( ) ;
let htlc_tx = chan_utils ::build_htlc_transaction ( & commitment_txid , trusted_tx . feerate_per_kw ( ) , holder_csv , & this_htlc , & keys . broadcaster_delayed_payment_key , & 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-10-15 13:45:18 +02:00
let htlc_redeemscript = chan_utils ::get_htlc_redeemscript ( & this_htlc , & 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-10-15 13:45:18 +02:00
let sighash = hash_to_message! ( & bip143 ::SigHashCache ::new ( & htlc_tx ) . signature_hash ( 0 , & htlc_redeemscript , this_htlc . amount_msat / 1000 , SigHashType ::All ) [ .. ] ) ;
secp_ctx . verify ( & sighash , sig , & 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
}
2021-01-05 11:50:54 -08:00
Ok ( self . inner . sign_holder_commitment_and_htlcs ( commitment_tx , secp_ctx ) . unwrap ( ) )
}
#[ cfg(any(test,feature = " unsafe_revoked_tx_signing " )) ]
2021-04-01 12:40:35 +02:00
fn unsafe_sign_holder_commitment_and_htlcs ( & self , commitment_tx : & HolderCommitmentTransaction , secp_ctx : & Secp256k1 < secp256k1 ::All > ) -> Result < ( Signature , Vec < Signature > ) , ( ) > {
2020-07-12 09:00:10 -07:00
Ok ( self . inner . unsafe_sign_holder_commitment_and_htlcs ( commitment_tx , secp_ctx ) . unwrap ( ) )
2020-03-21 15:39:19 -04:00
}
2021-05-15 17:20:10 -04:00
fn sign_justice_revoked_output ( & self , justice_tx : & Transaction , input : usize , amount : u64 , per_commitment_key : & SecretKey , secp_ctx : & Secp256k1 < secp256k1 ::All > ) -> Result < Signature , ( ) > {
Ok ( self . inner . sign_justice_revoked_output ( justice_tx , input , amount , per_commitment_key , secp_ctx ) . unwrap ( ) )
}
fn sign_justice_revoked_htlc ( & self , justice_tx : & Transaction , input : usize , amount : u64 , per_commitment_key : & SecretKey , htlc : & HTLCOutputInCommitment , secp_ctx : & Secp256k1 < secp256k1 ::All > ) -> Result < Signature , ( ) > {
Ok ( self . inner . sign_justice_revoked_htlc ( justice_tx , input , amount , per_commitment_key , htlc , secp_ctx ) . unwrap ( ) )
2020-03-24 14:22:16 -04:00
}
2021-04-01 12:40:35 +02:00
fn sign_counterparty_htlc_transaction ( & self , htlc_tx : & Transaction , input : usize , amount : u64 , per_commitment_point : & PublicKey , htlc : & HTLCOutputInCommitment , secp_ctx : & Secp256k1 < secp256k1 ::All > ) -> Result < Signature , ( ) > {
2020-08-31 15:31:19 -04:00
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
}
2021-04-01 12:40:35 +02:00
fn sign_closing_transaction ( & self , closing_tx : & Transaction , secp_ctx : & Secp256k1 < secp256k1 ::All > ) -> Result < Signature , ( ) > {
2020-01-23 14:32:29 -08:00
Ok ( self . inner . sign_closing_transaction ( closing_tx , secp_ctx ) . unwrap ( ) )
2019-12-13 01:57:45 -05:00
}
2021-04-01 12:40:35 +02:00
fn sign_channel_announcement ( & self , msg : & msgs ::UnsignedChannelAnnouncement , secp_ctx : & Secp256k1 < secp256k1 ::All > ) -> Result < Signature , ( ) > {
2019-12-07 17:54:55 -05:00
self . inner . sign_channel_announcement ( msg , secp_ctx )
}
2020-01-09 17:28:48 -08:00
2020-10-15 13:45:18 +02:00
fn ready_channel ( & mut self , channel_parameters : & ChannelTransactionParameters ) {
self . inner . ready_channel ( channel_parameters )
2020-01-09 17:28:48 -08:00
}
2019-11-26 16:46:33 -05:00
}
2021-04-01 12:24:21 +02:00
impl Sign for EnforcingSigner { }
2020-10-15 13:45:18 +02:00
2021-02-16 16:30:08 -05:00
impl Writeable for EnforcingSigner {
2020-02-04 09:15:59 -08:00
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , Error > {
self . inner . write ( writer ) ? ;
2020-10-15 13:45:18 +02:00
let last = * self . last_commitment_number . lock ( ) . unwrap ( ) ;
2020-02-04 09:15:59 -08:00
last . write ( writer ) ? ;
Ok ( ( ) )
}
}
2020-01-16 16:51:15 -08:00
2021-02-16 16:30:08 -05:00
impl Readable for EnforcingSigner {
2021-08-01 18:22:06 +02:00
fn read < R : io ::Read > ( reader : & mut R ) -> Result < Self , DecodeError > {
2021-01-13 17:36:07 -08:00
let inner = Readable ::read ( reader ) ? ;
2020-10-15 13:45:18 +02:00
let last_commitment_number = Readable ::read ( reader ) ? ;
2021-02-16 16:30:08 -05:00
Ok ( EnforcingSigner {
2020-10-15 13:45:18 +02:00
inner ,
2020-07-12 09:00:10 -07:00
last_commitment_number : Arc ::new ( Mutex ::new ( last_commitment_number ) ) ,
revoked_commitment : Arc ::new ( Mutex ::new ( INITIAL_REVOKED_COMMITMENT_NUMBER ) ) ,
2021-01-13 17:36:07 -08:00
disable_revocation_policy_check : false ,
2020-02-04 09:15:59 -08:00
} )
}
}
2020-10-15 13:45:18 +02:00
2021-02-16 16:30:08 -05:00
impl EnforcingSigner {
2020-10-15 13:45:18 +02:00
fn verify_counterparty_commitment_tx < ' a , T : secp256k1 ::Signing + secp256k1 ::Verification > ( & self , commitment_tx : & ' a CommitmentTransaction , secp_ctx : & Secp256k1 < T > ) -> TrustedCommitmentTransaction < ' a > {
commitment_tx . verify ( & self . inner . get_channel_parameters ( ) . as_counterparty_broadcastable ( ) ,
self . inner . counterparty_pubkeys ( ) , self . inner . pubkeys ( ) , secp_ctx )
. expect ( " derived different per-tx keys or built transaction " )
}
fn verify_holder_commitment_tx < ' a , T : secp256k1 ::Signing + secp256k1 ::Verification > ( & self , commitment_tx : & ' a CommitmentTransaction , secp_ctx : & Secp256k1 < T > ) -> TrustedCommitmentTransaction < ' a > {
commitment_tx . verify ( & self . inner . get_channel_parameters ( ) . as_holder_broadcastable ( ) ,
self . inner . pubkeys ( ) , self . inner . counterparty_pubkeys ( ) , secp_ctx )
. expect ( " derived different per-tx keys or built transaction " )
}
}