2019-11-27 16:08:48 -05:00
//! Various utilities for building scripts and deriving keys related to channels. These are
//! largely of interest for those implementing chain::keysinterface::ChannelKeys message signing
//! by hand.
2017-12-25 01:05:27 -05:00
use bitcoin ::blockdata ::script ::{ Script , Builder } ;
use bitcoin ::blockdata ::opcodes ;
2019-12-13 01:58:08 -05:00
use bitcoin ::blockdata ::transaction ::{ TxIn , TxOut , OutPoint , Transaction , SigHashType } ;
use bitcoin ::consensus ::encode ::{ self , Decodable , Encodable } ;
use bitcoin ::util ::bip143 ;
2017-12-25 01:05:27 -05:00
2018-12-17 23:58:02 -05:00
use bitcoin_hashes ::{ Hash , HashEngine } ;
use bitcoin_hashes ::sha256 ::Hash as Sha256 ;
2018-12-13 16:23:22 -05:00
use bitcoin_hashes ::ripemd160 ::Hash as Ripemd160 ;
use bitcoin_hashes ::hash160 ::Hash as Hash160 ;
2019-03-04 18:02:02 +01:00
use bitcoin_hashes ::sha256d ::Hash as Sha256dHash ;
2018-12-17 23:58:02 -05:00
2019-12-13 14:56:57 -05:00
use ln ::channelmanager ::{ PaymentHash , PaymentPreimage } ;
2019-12-13 01:58:08 -05:00
use ln ::msgs ::DecodeError ;
use util ::ser ::{ Readable , Writeable , Writer , WriterWriteAdaptor } ;
2020-02-07 16:05:24 -05:00
use util ::byte_utils ;
2018-11-22 21:18:16 -05:00
2020-01-17 14:31:29 -08:00
use secp256k1 ::key ::{ SecretKey , PublicKey } ;
2019-12-13 01:58:08 -05:00
use secp256k1 ::{ Secp256k1 , Signature } ;
2017-12-25 01:05:27 -05:00
use secp256k1 ;
2019-11-27 16:08:48 -05:00
pub ( super ) const HTLC_SUCCESS_TX_WEIGHT : u64 = 703 ;
pub ( super ) const HTLC_TIMEOUT_TX_WEIGHT : u64 = 663 ;
2018-04-24 00:19:52 -04:00
2020-01-14 13:47:01 -05:00
#[ derive(PartialEq) ]
pub ( crate ) enum HTLCType {
AcceptedHTLC ,
OfferedHTLC
}
impl HTLCType {
/// Check if a given tx witnessScript len matchs one of a pre-signed HTLC
pub ( crate ) fn scriptlen_to_htlctype ( witness_script_len : usize ) -> Option < HTLCType > {
if witness_script_len = = 133 {
Some ( HTLCType ::OfferedHTLC )
} else if witness_script_len > = 136 & & witness_script_len < = 139 {
Some ( HTLCType ::AcceptedHTLC )
} else {
None
}
}
}
2017-12-25 01:05:27 -05:00
// Various functions for key derivation and transaction creation for use within channels. Primarily
// used in Channel and ChannelMonitor.
2019-11-27 16:08:48 -05:00
pub ( super ) fn build_commitment_secret ( commitment_seed : & [ u8 ; 32 ] , idx : u64 ) -> [ u8 ; 32 ] {
2019-11-26 16:46:33 -05:00
let mut res : [ u8 ; 32 ] = commitment_seed . clone ( ) ;
2017-12-25 01:05:27 -05:00
for i in 0 .. 48 {
let bitpos = 47 - i ;
if idx & ( 1 < < bitpos ) = = ( 1 < < bitpos ) {
res [ bitpos / 8 ] ^ = 1 < < ( bitpos & 7 ) ;
2018-12-17 23:58:02 -05:00
res = Sha256 ::hash ( & res ) . into_inner ( ) ;
2017-12-25 01:05:27 -05:00
}
}
res
}
2020-02-07 16:05:24 -05:00
/// Implements the per-commitment secret storage scheme from
/// [BOLT 3](https://github.com/lightningnetwork/lightning-rfc/blob/dcbf8583976df087c79c3ce0b535311212e6812d/03-transactions.md#efficient-per-commitment-secret-storage).
///
/// Allows us to keep track of all of the revocation secrets of counterarties in just 50*32 bytes
/// or so.
#[ derive(Clone) ]
pub ( super ) struct CounterpartyCommitmentSecrets {
old_secrets : [ ( [ u8 ; 32 ] , u64 ) ; 49 ] ,
}
impl PartialEq for CounterpartyCommitmentSecrets {
fn eq ( & self , other : & Self ) -> bool {
for ( & ( ref secret , ref idx ) , & ( ref o_secret , ref o_idx ) ) in self . old_secrets . iter ( ) . zip ( other . old_secrets . iter ( ) ) {
if secret ! = o_secret | | idx ! = o_idx {
return false
}
}
true
}
}
impl CounterpartyCommitmentSecrets {
pub ( super ) fn new ( ) -> Self {
Self { old_secrets : [ ( [ 0 ; 32 ] , 1 < < 48 ) ; 49 ] , }
}
#[ inline ]
fn place_secret ( idx : u64 ) -> u8 {
for i in 0 .. 48 {
if idx & ( 1 < < i ) = = ( 1 < < i ) {
return i
}
}
48
}
pub ( super ) fn get_min_seen_secret ( & self ) -> u64 {
//TODO This can be optimized?
let mut min = 1 < < 48 ;
for & ( _ , idx ) in self . old_secrets . iter ( ) {
if idx < min {
min = idx ;
}
}
min
}
#[ inline ]
pub ( super ) fn derive_secret ( secret : [ u8 ; 32 ] , bits : u8 , idx : u64 ) -> [ u8 ; 32 ] {
let mut res : [ u8 ; 32 ] = secret ;
for i in 0 .. bits {
let bitpos = bits - 1 - i ;
if idx & ( 1 < < bitpos ) = = ( 1 < < bitpos ) {
res [ ( bitpos / 8 ) as usize ] ^ = 1 < < ( bitpos & 7 ) ;
res = Sha256 ::hash ( & res ) . into_inner ( ) ;
}
}
res
}
pub ( super ) fn provide_secret ( & mut self , idx : u64 , secret : [ u8 ; 32 ] ) -> Result < ( ) , ( ) > {
let pos = Self ::place_secret ( idx ) ;
for i in 0 .. pos {
let ( old_secret , old_idx ) = self . old_secrets [ i as usize ] ;
if Self ::derive_secret ( secret , pos , old_idx ) ! = old_secret {
return Err ( ( ) ) ;
}
}
if self . get_min_seen_secret ( ) < = idx {
return Ok ( ( ) ) ;
}
self . old_secrets [ pos as usize ] = ( secret , idx ) ;
Ok ( ( ) )
}
/// Can only fail if idx is < get_min_seen_secret
pub ( super ) fn get_secret ( & self , idx : u64 ) -> Option < [ u8 ; 32 ] > {
for i in 0 .. self . old_secrets . len ( ) {
if ( idx & ( ! ( ( 1 < < i ) - 1 ) ) ) = = self . old_secrets [ i ] . 1 {
return Some ( Self ::derive_secret ( self . old_secrets [ i ] . 0 , i as u8 , idx ) )
}
}
assert! ( idx < self . get_min_seen_secret ( ) ) ;
None
}
}
impl Writeable for CounterpartyCommitmentSecrets {
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , ::std ::io ::Error > {
for & ( ref secret , ref idx ) in self . old_secrets . iter ( ) {
writer . write_all ( secret ) ? ;
writer . write_all ( & byte_utils ::be64_to_array ( * idx ) ) ? ;
}
Ok ( ( ) )
}
}
impl < R : ::std ::io ::Read > Readable < R > for CounterpartyCommitmentSecrets {
fn read ( reader : & mut R ) -> Result < Self , DecodeError > {
let mut old_secrets = [ ( [ 0 ; 32 ] , 1 < < 48 ) ; 49 ] ;
for & mut ( ref mut secret , ref mut idx ) in old_secrets . iter_mut ( ) {
* secret = Readable ::read ( reader ) ? ;
* idx = Readable ::read ( reader ) ? ;
}
Ok ( Self { old_secrets } )
}
}
2019-11-27 16:08:48 -05:00
/// Derives a per-commitment-transaction private key (eg an htlc key or payment key) from the base
/// private key for that type of key and the per_commitment_point (available in TxCreationKeys)
2018-08-20 17:13:07 -04:00
pub fn derive_private_key < T : secp256k1 ::Signing > ( secp_ctx : & Secp256k1 < T > , per_commitment_point : & PublicKey , base_secret : & SecretKey ) -> Result < SecretKey , secp256k1 ::Error > {
2018-12-17 23:58:02 -05:00
let mut sha = Sha256 ::engine ( ) ;
2017-12-25 01:05:27 -05:00
sha . input ( & per_commitment_point . serialize ( ) ) ;
2018-08-20 17:13:07 -04:00
sha . input ( & PublicKey ::from_secret_key ( & secp_ctx , & base_secret ) . serialize ( ) ) ;
2018-12-17 23:58:02 -05:00
let res = Sha256 ::from_engine ( sha ) . into_inner ( ) ;
2017-12-25 01:05:27 -05:00
let mut key = base_secret . clone ( ) ;
2019-01-16 15:45:05 -05:00
key . add_assign ( & res ) ? ;
2017-12-25 01:05:27 -05:00
Ok ( key )
}
2019-11-27 16:08:48 -05:00
pub ( super ) fn derive_public_key < T : secp256k1 ::Signing > ( secp_ctx : & Secp256k1 < T > , per_commitment_point : & PublicKey , base_point : & PublicKey ) -> Result < PublicKey , secp256k1 ::Error > {
2018-12-17 23:58:02 -05:00
let mut sha = Sha256 ::engine ( ) ;
2017-12-25 01:05:27 -05:00
sha . input ( & per_commitment_point . serialize ( ) ) ;
sha . input ( & base_point . serialize ( ) ) ;
2018-12-17 23:58:02 -05:00
let res = Sha256 ::from_engine ( sha ) . into_inner ( ) ;
2017-12-25 01:05:27 -05:00
2019-01-16 15:45:05 -05:00
let hashkey = PublicKey ::from_secret_key ( & secp_ctx , & SecretKey ::from_slice ( & res ) ? ) ;
base_point . combine ( & hashkey )
2017-12-25 01:05:27 -05:00
}
2019-12-13 14:56:57 -05:00
/// Derives a revocation key from its constituent parts.
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
/// generated (ie our own).
2019-11-27 16:08:48 -05:00
pub ( super ) fn derive_private_revocation_key < T : secp256k1 ::Signing > ( secp_ctx : & Secp256k1 < T > , per_commitment_secret : & SecretKey , revocation_base_secret : & SecretKey ) -> Result < SecretKey , secp256k1 ::Error > {
2018-08-20 17:13:07 -04:00
let revocation_base_point = PublicKey ::from_secret_key ( & secp_ctx , & revocation_base_secret ) ;
let per_commitment_point = PublicKey ::from_secret_key ( & secp_ctx , & per_commitment_secret ) ;
2017-12-25 01:05:27 -05:00
let rev_append_commit_hash_key = {
2018-12-17 23:58:02 -05:00
let mut sha = Sha256 ::engine ( ) ;
2017-12-25 01:05:27 -05:00
sha . input ( & revocation_base_point . serialize ( ) ) ;
sha . input ( & per_commitment_point . serialize ( ) ) ;
2019-01-16 15:45:05 -05:00
Sha256 ::from_engine ( sha ) . into_inner ( )
2017-12-25 01:05:27 -05:00
} ;
let commit_append_rev_hash_key = {
2018-12-17 23:58:02 -05:00
let mut sha = Sha256 ::engine ( ) ;
2017-12-25 01:05:27 -05:00
sha . input ( & per_commitment_point . serialize ( ) ) ;
sha . input ( & revocation_base_point . serialize ( ) ) ;
2019-01-16 15:45:05 -05:00
Sha256 ::from_engine ( sha ) . into_inner ( )
2017-12-25 01:05:27 -05:00
} ;
let mut part_a = revocation_base_secret . clone ( ) ;
2019-01-16 15:45:05 -05:00
part_a . mul_assign ( & rev_append_commit_hash_key ) ? ;
2017-12-25 01:05:27 -05:00
let mut part_b = per_commitment_secret . clone ( ) ;
2019-01-16 15:45:05 -05:00
part_b . mul_assign ( & commit_append_rev_hash_key ) ? ;
part_a . add_assign ( & part_b [ .. ] ) ? ;
2017-12-25 01:05:27 -05:00
Ok ( part_a )
}
2019-11-27 16:08:48 -05:00
pub ( super ) fn derive_public_revocation_key < T : secp256k1 ::Verification > ( secp_ctx : & Secp256k1 < T > , per_commitment_point : & PublicKey , revocation_base_point : & PublicKey ) -> Result < PublicKey , secp256k1 ::Error > {
2017-12-25 01:05:27 -05:00
let rev_append_commit_hash_key = {
2018-12-17 23:58:02 -05:00
let mut sha = Sha256 ::engine ( ) ;
2017-12-25 01:05:27 -05:00
sha . input ( & revocation_base_point . serialize ( ) ) ;
sha . input ( & per_commitment_point . serialize ( ) ) ;
2019-01-16 15:45:05 -05:00
Sha256 ::from_engine ( sha ) . into_inner ( )
2017-12-25 01:05:27 -05:00
} ;
let commit_append_rev_hash_key = {
2018-12-17 23:58:02 -05:00
let mut sha = Sha256 ::engine ( ) ;
2017-12-25 01:05:27 -05:00
sha . input ( & per_commitment_point . serialize ( ) ) ;
sha . input ( & revocation_base_point . serialize ( ) ) ;
2019-01-16 15:45:05 -05:00
Sha256 ::from_engine ( sha ) . into_inner ( )
2017-12-25 01:05:27 -05:00
} ;
let mut part_a = revocation_base_point . clone ( ) ;
2018-03-01 09:54:56 +01:00
part_a . mul_assign ( & secp_ctx , & rev_append_commit_hash_key ) ? ;
2017-12-25 01:05:27 -05:00
let mut part_b = per_commitment_point . clone ( ) ;
2018-03-01 09:54:56 +01:00
part_b . mul_assign ( & secp_ctx , & commit_append_rev_hash_key ) ? ;
2019-01-16 15:45:05 -05:00
part_a . combine ( & part_b )
2017-12-25 01:05:27 -05:00
}
2019-11-27 16:08:48 -05:00
/// The set of public keys which are used in the creation of one commitment transaction.
/// These are derived from the channel base keys and per-commitment data.
2020-02-06 13:53:56 -05:00
#[ derive(PartialEq, Clone) ]
2017-12-25 01:05:27 -05:00
pub struct TxCreationKeys {
2019-11-27 16:08:48 -05:00
/// The per-commitment public key which was used to derive the other keys.
2017-12-25 01:05:27 -05:00
pub per_commitment_point : PublicKey ,
2019-11-27 16:08:48 -05:00
/// The revocation key which is used to allow the owner of the commitment transaction to
/// provide their counterparty the ability to punish them if they broadcast an old state.
2020-01-17 12:46:54 -08:00
pub ( crate ) revocation_key : PublicKey ,
2019-11-27 16:08:48 -05:00
/// A's HTLC Key
2020-01-17 12:46:54 -08:00
pub ( crate ) a_htlc_key : PublicKey ,
2019-11-27 16:08:48 -05:00
/// B's HTLC Key
2020-01-17 12:46:54 -08:00
pub ( crate ) b_htlc_key : PublicKey ,
2019-11-27 16:08:48 -05:00
/// A's Payment Key (which isn't allowed to be spent from for some delay)
2020-01-17 12:46:54 -08:00
pub ( crate ) a_delayed_payment_key : PublicKey ,
2019-11-27 16:08:48 -05:00
/// B's Payment Key
2020-01-17 12:46:54 -08:00
pub ( crate ) b_payment_key : PublicKey ,
2017-12-25 01:05:27 -05:00
}
2020-02-06 13:53:56 -05:00
impl_writeable! ( TxCreationKeys , 33 * 6 ,
{ per_commitment_point , revocation_key , a_htlc_key , b_htlc_key , a_delayed_payment_key , b_payment_key } ) ;
2017-12-25 01:05:27 -05:00
2020-01-16 16:51:15 -08:00
/// One counterparty's public keys which do not change over the life of a channel.
2020-02-04 09:15:59 -08:00
#[ derive(Clone, PartialEq) ]
2020-01-16 16:51:15 -08:00
pub struct ChannelPublicKeys {
/// The public key which is used to sign all commitment transactions, as it appears in the
/// on-chain channel lock-in 2-of-2 multisig output.
pub funding_pubkey : PublicKey ,
/// The base point which is used (with derive_public_revocation_key) to derive per-commitment
/// revocation keys. The per-commitment revocation private key is then revealed by the owner of
/// a commitment transaction so that their counterparty can claim all available funds if they
/// broadcast an old state.
pub revocation_basepoint : PublicKey ,
/// The base point which is used (with derive_public_key) to derive a per-commitment payment
/// public key which receives immediately-spendable non-HTLC-encumbered funds.
pub payment_basepoint : PublicKey ,
/// The base point which is used (with derive_public_key) to derive a per-commitment payment
/// public key which receives non-HTLC-encumbered funds which are only available for spending
/// after some delay (or can be claimed via the revocation path).
pub delayed_payment_basepoint : PublicKey ,
/// The base point which is used (with derive_public_key) to derive a per-commitment public key
/// which is used to encumber HTLC-in-flight outputs.
pub htlc_basepoint : PublicKey ,
2017-12-25 01:05:27 -05:00
}
2020-01-16 16:51:15 -08:00
impl_writeable! ( ChannelPublicKeys , 33 * 5 , {
funding_pubkey ,
revocation_basepoint ,
payment_basepoint ,
delayed_payment_basepoint ,
htlc_basepoint
} ) ;
2017-12-25 01:05:27 -05:00
impl TxCreationKeys {
2020-01-16 16:51:15 -08:00
pub ( crate ) fn new < T : secp256k1 ::Signing + secp256k1 ::Verification > ( secp_ctx : & Secp256k1 < T > , per_commitment_point : & PublicKey , a_delayed_payment_base : & PublicKey , a_htlc_base : & PublicKey , b_revocation_base : & PublicKey , b_payment_base : & PublicKey , b_htlc_base : & PublicKey ) -> Result < TxCreationKeys , secp256k1 ::Error > {
2017-12-25 01:05:27 -05:00
Ok ( TxCreationKeys {
per_commitment_point : per_commitment_point . clone ( ) ,
2018-03-01 09:54:56 +01:00
revocation_key : derive_public_revocation_key ( & secp_ctx , & per_commitment_point , & b_revocation_base ) ? ,
a_htlc_key : derive_public_key ( & secp_ctx , & per_commitment_point , & a_htlc_base ) ? ,
b_htlc_key : derive_public_key ( & secp_ctx , & per_commitment_point , & b_htlc_base ) ? ,
a_delayed_payment_key : derive_public_key ( & secp_ctx , & per_commitment_point , & a_delayed_payment_base ) ? ,
b_payment_key : derive_public_key ( & secp_ctx , & per_commitment_point , & b_payment_base ) ? ,
2017-12-25 01:05:27 -05:00
} )
}
}
/// Gets the "to_local" output redeemscript, ie the script which is time-locked or spendable by
/// the revocation key
2019-11-27 16:08:48 -05:00
pub ( super ) fn get_revokeable_redeemscript ( revocation_key : & PublicKey , to_self_delay : u16 , delayed_payment_key : & PublicKey ) -> Script {
2019-01-16 15:45:05 -05:00
Builder ::new ( ) . push_opcode ( opcodes ::all ::OP_IF )
2018-06-29 16:02:19 -04:00
. push_slice ( & revocation_key . serialize ( ) )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_ELSE )
2018-06-29 16:02:19 -04:00
. push_int ( to_self_delay as i64 )
2019-08-23 19:12:55 -04:00
. push_opcode ( opcodes ::all ::OP_CSV )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_DROP )
2018-06-29 16:02:19 -04:00
. push_slice ( & delayed_payment_key . serialize ( ) )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_ENDIF )
. push_opcode ( opcodes ::all ::OP_CHECKSIG )
2018-06-29 16:02:19 -04:00
. into_script ( )
2017-12-25 01:05:27 -05:00
}
2018-07-16 21:12:54 -07:00
#[ derive(Clone, PartialEq) ]
2019-11-27 16:08:48 -05:00
/// Information about an HTLC as it appears in a commitment transaction
2017-12-25 01:05:27 -05:00
pub struct HTLCOutputInCommitment {
2019-11-27 16:08:48 -05:00
/// Whether the HTLC was "offered" (ie outbound in relation to this commitment transaction).
/// Note that this is not the same as whether it is ountbound *from us*. To determine that you
/// need to compare this value to whether the commitment transaction in question is that of
/// the remote party or our own.
2017-12-25 01:05:27 -05:00
pub offered : bool ,
2019-11-27 16:08:48 -05:00
/// The value, in msat, of the HTLC. The value as it appears in the commitment transaction is
/// this divided by 1000.
2017-12-25 01:05:27 -05:00
pub amount_msat : u64 ,
2019-11-27 16:08:48 -05:00
/// The CLTV lock-time at which this HTLC expires.
2017-12-25 01:05:27 -05:00
pub cltv_expiry : u32 ,
2019-11-27 16:08:48 -05:00
/// The hash of the preimage which unlocks this HTLC.
2018-11-22 21:18:16 -05:00
pub payment_hash : PaymentHash ,
2019-11-27 16:08:48 -05:00
/// The position within the commitment transactions' outputs. This may be None if the value is
/// below the dust limit (in which case no output appears in the commitment transaction and the
/// value is spent to additional transaction fees).
2019-01-06 17:02:53 -05:00
pub transaction_output_index : Option < u32 > ,
2017-12-25 01:05:27 -05:00
}
2020-02-06 13:53:56 -05:00
impl_writeable! ( HTLCOutputInCommitment , 1 + 8 + 4 + 32 + 5 , {
offered ,
amount_msat ,
cltv_expiry ,
payment_hash ,
transaction_output_index
} ) ;
2017-12-25 01:05:27 -05:00
#[ inline ]
2019-11-27 16:08:48 -05:00
pub ( super ) fn get_htlc_redeemscript_with_explicit_keys ( htlc : & HTLCOutputInCommitment , a_htlc_key : & PublicKey , b_htlc_key : & PublicKey , revocation_key : & PublicKey ) -> Script {
2018-12-13 16:23:22 -05:00
let payment_hash160 = Ripemd160 ::hash ( & htlc . payment_hash . 0 [ .. ] ) . into_inner ( ) ;
2018-04-08 21:01:13 -04:00
if htlc . offered {
2019-01-16 15:45:05 -05:00
Builder ::new ( ) . push_opcode ( opcodes ::all ::OP_DUP )
. push_opcode ( opcodes ::all ::OP_HASH160 )
2018-12-13 16:23:22 -05:00
. push_slice ( & Hash160 ::hash ( & revocation_key . serialize ( ) ) [ .. ] )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_EQUAL )
. push_opcode ( opcodes ::all ::OP_IF )
. push_opcode ( opcodes ::all ::OP_CHECKSIG )
. push_opcode ( opcodes ::all ::OP_ELSE )
2017-12-25 01:05:27 -05:00
. push_slice ( & b_htlc_key . serialize ( ) [ .. ] )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_SWAP )
. push_opcode ( opcodes ::all ::OP_SIZE )
2017-12-25 01:05:27 -05:00
. push_int ( 32 )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_EQUAL )
. push_opcode ( opcodes ::all ::OP_NOTIF )
. push_opcode ( opcodes ::all ::OP_DROP )
2017-12-25 01:05:27 -05:00
. push_int ( 2 )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_SWAP )
2017-12-25 01:05:27 -05:00
. push_slice ( & a_htlc_key . serialize ( ) [ .. ] )
. push_int ( 2 )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_CHECKMULTISIG )
. push_opcode ( opcodes ::all ::OP_ELSE )
. push_opcode ( opcodes ::all ::OP_HASH160 )
2017-12-25 01:05:27 -05:00
. push_slice ( & payment_hash160 )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_EQUALVERIFY )
. push_opcode ( opcodes ::all ::OP_CHECKSIG )
. push_opcode ( opcodes ::all ::OP_ENDIF )
. push_opcode ( opcodes ::all ::OP_ENDIF )
2017-12-25 01:05:27 -05:00
. into_script ( )
} else {
2019-01-16 15:45:05 -05:00
Builder ::new ( ) . push_opcode ( opcodes ::all ::OP_DUP )
. push_opcode ( opcodes ::all ::OP_HASH160 )
2018-12-13 16:23:22 -05:00
. push_slice ( & Hash160 ::hash ( & revocation_key . serialize ( ) ) [ .. ] )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_EQUAL )
. push_opcode ( opcodes ::all ::OP_IF )
. push_opcode ( opcodes ::all ::OP_CHECKSIG )
. push_opcode ( opcodes ::all ::OP_ELSE )
2017-12-25 01:05:27 -05:00
. push_slice ( & b_htlc_key . serialize ( ) [ .. ] )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_SWAP )
. push_opcode ( opcodes ::all ::OP_SIZE )
2017-12-25 01:05:27 -05:00
. push_int ( 32 )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_EQUAL )
. push_opcode ( opcodes ::all ::OP_IF )
. push_opcode ( opcodes ::all ::OP_HASH160 )
2017-12-25 01:05:27 -05:00
. push_slice ( & payment_hash160 )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_EQUALVERIFY )
2017-12-25 01:05:27 -05:00
. push_int ( 2 )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_SWAP )
2017-12-25 01:05:27 -05:00
. push_slice ( & a_htlc_key . serialize ( ) [ .. ] )
. push_int ( 2 )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_CHECKMULTISIG )
. push_opcode ( opcodes ::all ::OP_ELSE )
. push_opcode ( opcodes ::all ::OP_DROP )
2017-12-25 01:05:27 -05:00
. push_int ( htlc . cltv_expiry as i64 )
2019-08-23 19:12:55 -04:00
. push_opcode ( opcodes ::all ::OP_CLTV )
2019-01-16 15:45:05 -05:00
. push_opcode ( opcodes ::all ::OP_DROP )
. push_opcode ( opcodes ::all ::OP_CHECKSIG )
. push_opcode ( opcodes ::all ::OP_ENDIF )
. push_opcode ( opcodes ::all ::OP_ENDIF )
2017-12-25 01:05:27 -05:00
. into_script ( )
}
}
/// note here that 'a_revocation_key' is generated using b_revocation_basepoint and a's
/// commitment secret. 'htlc' does *not* need to have its previous_output_index filled.
#[ inline ]
2018-04-02 18:00:55 -04:00
pub fn get_htlc_redeemscript ( htlc : & HTLCOutputInCommitment , keys : & TxCreationKeys ) -> Script {
2018-04-08 21:01:13 -04:00
get_htlc_redeemscript_with_explicit_keys ( htlc , & keys . a_htlc_key , & keys . b_htlc_key , & keys . revocation_key )
2017-12-25 01:05:27 -05:00
}
2018-04-24 00:19:52 -04:00
2020-01-09 17:28:48 -08:00
/// Gets the redeemscript for a funding output from the two funding public keys.
/// Note that the order of funding public keys does not matter.
pub fn make_funding_redeemscript ( a : & PublicKey , b : & PublicKey ) -> Script {
let our_funding_key = a . serialize ( ) ;
let their_funding_key = b . serialize ( ) ;
let builder = Builder ::new ( ) . push_opcode ( opcodes ::all ::OP_PUSHNUM_2 ) ;
if our_funding_key [ .. ] < their_funding_key [ .. ] {
builder . push_slice ( & our_funding_key )
. push_slice ( & their_funding_key )
} else {
builder . push_slice ( & their_funding_key )
. push_slice ( & our_funding_key )
} . push_opcode ( opcodes ::all ::OP_PUSHNUM_2 ) . push_opcode ( opcodes ::all ::OP_CHECKMULTISIG ) . into_script ( )
}
2019-01-06 17:02:53 -05:00
/// panics if htlc.transaction_output_index.is_none()!
2018-04-24 00:19:52 -04:00
pub fn build_htlc_transaction ( prev_hash : & Sha256dHash , feerate_per_kw : u64 , to_self_delay : u16 , htlc : & HTLCOutputInCommitment , a_delayed_payment_key : & PublicKey , revocation_key : & PublicKey ) -> Transaction {
let mut txins : Vec < TxIn > = Vec ::new ( ) ;
txins . push ( TxIn {
2018-08-20 17:13:07 -04:00
previous_output : OutPoint {
txid : prev_hash . clone ( ) ,
2019-01-06 17:02:53 -05:00
vout : htlc . transaction_output_index . expect ( " Can't build an HTLC transaction for a dust output " ) ,
2018-08-20 17:13:07 -04:00
} ,
2018-04-24 00:19:52 -04:00
script_sig : Script ::new ( ) ,
sequence : 0 ,
witness : Vec ::new ( ) ,
} ) ;
let total_fee = if htlc . offered {
feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000
} else {
feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000
} ;
let mut txouts : Vec < TxOut > = Vec ::new ( ) ;
txouts . push ( TxOut {
script_pubkey : get_revokeable_redeemscript ( revocation_key , to_self_delay , a_delayed_payment_key ) . to_v0_p2wsh ( ) ,
value : htlc . amount_msat / 1000 - total_fee //TODO: BOLT 3 does not specify if we should add amount_msat before dividing or if we should divide by 1000 before subtracting (as we do here)
} ) ;
Transaction {
version : 2 ,
lock_time : if htlc . offered { htlc . cltv_expiry } else { 0 } ,
input : txins ,
output : txouts ,
}
}
2019-12-13 01:58:08 -05:00
2019-12-13 14:56:57 -05:00
/// Signs a transaction created by build_htlc_transaction. If the transaction is an
/// HTLC-Success transaction (ie htlc.offered is false), preimage must be set!
pub ( crate ) fn sign_htlc_transaction < T : secp256k1 ::Signing > ( tx : & mut Transaction , their_sig : & Signature , preimage : & Option < PaymentPreimage > , htlc : & HTLCOutputInCommitment , a_htlc_key : & PublicKey , b_htlc_key : & PublicKey , revocation_key : & PublicKey , per_commitment_point : & PublicKey , htlc_base_key : & SecretKey , secp_ctx : & Secp256k1 < T > ) -> Result < ( Signature , Script ) , ( ) > {
if tx . input . len ( ) ! = 1 { return Err ( ( ) ) ; }
if tx . input [ 0 ] . witness . len ( ) ! = 0 { return Err ( ( ) ) ; }
let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys ( & htlc , a_htlc_key , b_htlc_key , revocation_key ) ;
let our_htlc_key = derive_private_key ( secp_ctx , per_commitment_point , htlc_base_key ) . map_err ( | _ | ( ) ) ? ;
let sighash = hash_to_message! ( & bip143 ::SighashComponents ::new ( & tx ) . sighash_all ( & tx . input [ 0 ] , & htlc_redeemscript , htlc . amount_msat / 1000 ) [ .. ] ) ;
let local_tx = PublicKey ::from_secret_key ( & secp_ctx , & our_htlc_key ) = = * a_htlc_key ;
let our_sig = secp_ctx . sign ( & sighash , & our_htlc_key ) ;
tx . input [ 0 ] . witness . push ( Vec ::new ( ) ) ; // First is the multisig dummy
if local_tx { // b, then a
tx . input [ 0 ] . witness . push ( their_sig . serialize_der ( ) . to_vec ( ) ) ;
tx . input [ 0 ] . witness . push ( our_sig . serialize_der ( ) . to_vec ( ) ) ;
} else {
tx . input [ 0 ] . witness . push ( our_sig . serialize_der ( ) . to_vec ( ) ) ;
tx . input [ 0 ] . witness . push ( their_sig . serialize_der ( ) . to_vec ( ) ) ;
}
tx . input [ 0 ] . witness [ 1 ] . push ( SigHashType ::All as u8 ) ;
tx . input [ 0 ] . witness [ 2 ] . push ( SigHashType ::All as u8 ) ;
if htlc . offered {
tx . input [ 0 ] . witness . push ( Vec ::new ( ) ) ;
assert! ( preimage . is_none ( ) ) ;
} else {
tx . input [ 0 ] . witness . push ( preimage . unwrap ( ) . 0. to_vec ( ) ) ;
}
tx . input [ 0 ] . witness . push ( htlc_redeemscript . as_bytes ( ) . to_vec ( ) ) ;
Ok ( ( our_sig , htlc_redeemscript ) )
}
2019-12-13 01:58:08 -05:00
#[ derive(Clone) ]
/// We use this to track local commitment transactions and put off signing them until we are ready
/// to broadcast. Eventually this will require a signer which is possibly external, but for now we
/// just pass in the SecretKeys required.
pub ( crate ) struct LocalCommitmentTransaction {
tx : Transaction
}
impl LocalCommitmentTransaction {
#[ cfg(test) ]
pub fn dummy ( ) -> Self {
Self { tx : Transaction {
version : 2 ,
input : Vec ::new ( ) ,
output : Vec ::new ( ) ,
lock_time : 0 ,
} }
}
pub fn new_missing_local_sig ( mut tx : Transaction , their_sig : & Signature , our_funding_key : & PublicKey , their_funding_key : & PublicKey ) -> LocalCommitmentTransaction {
if tx . input . len ( ) ! = 1 { panic! ( " Tried to store a commitment transaction that had input count != 1! " ) ; }
if tx . input [ 0 ] . witness . len ( ) ! = 0 { panic! ( " Tried to store a signed commitment transaction? " ) ; }
tx . input [ 0 ] . witness . push ( Vec ::new ( ) ) ; // First is the multisig dummy
if our_funding_key . serialize ( ) [ .. ] < their_funding_key . serialize ( ) [ .. ] {
tx . input [ 0 ] . witness . push ( Vec ::new ( ) ) ;
tx . input [ 0 ] . witness . push ( their_sig . serialize_der ( ) . to_vec ( ) ) ;
tx . input [ 0 ] . witness [ 2 ] . push ( SigHashType ::All as u8 ) ;
} else {
tx . input [ 0 ] . witness . push ( their_sig . serialize_der ( ) . to_vec ( ) ) ;
tx . input [ 0 ] . witness [ 1 ] . push ( SigHashType ::All as u8 ) ;
tx . input [ 0 ] . witness . push ( Vec ::new ( ) ) ;
}
Self { tx }
}
pub fn txid ( & self ) -> Sha256dHash {
self . tx . txid ( )
}
pub fn has_local_sig ( & self ) -> bool {
if self . tx . input . len ( ) ! = 1 { panic! ( " Commitment transactions must have input count == 1! " ) ; }
if self . tx . input [ 0 ] . witness . len ( ) = = 4 {
assert! ( ! self . tx . input [ 0 ] . witness [ 1 ] . is_empty ( ) ) ;
assert! ( ! self . tx . input [ 0 ] . witness [ 2 ] . is_empty ( ) ) ;
true
} else {
assert_eq! ( self . tx . input [ 0 ] . witness . len ( ) , 3 ) ;
assert! ( self . tx . input [ 0 ] . witness [ 0 ] . is_empty ( ) ) ;
assert! ( self . tx . input [ 0 ] . witness [ 1 ] . is_empty ( ) | | self . tx . input [ 0 ] . witness [ 2 ] . is_empty ( ) ) ;
false
}
}
pub fn add_local_sig < T : secp256k1 ::Signing > ( & mut self , funding_key : & SecretKey , funding_redeemscript : & Script , channel_value_satoshis : u64 , secp_ctx : & Secp256k1 < T > ) {
if self . has_local_sig ( ) { return ; }
let sighash = hash_to_message! ( & bip143 ::SighashComponents ::new ( & self . tx )
. sighash_all ( & self . tx . input [ 0 ] , funding_redeemscript , channel_value_satoshis ) [ .. ] ) ;
let our_sig = secp_ctx . sign ( & sighash , funding_key ) ;
if self . tx . input [ 0 ] . witness [ 1 ] . is_empty ( ) {
self . tx . input [ 0 ] . witness [ 1 ] = our_sig . serialize_der ( ) . to_vec ( ) ;
self . tx . input [ 0 ] . witness [ 1 ] . push ( SigHashType ::All as u8 ) ;
} else {
self . tx . input [ 0 ] . witness [ 2 ] = our_sig . serialize_der ( ) . to_vec ( ) ;
self . tx . input [ 0 ] . witness [ 2 ] . push ( SigHashType ::All as u8 ) ;
}
self . tx . input [ 0 ] . witness . push ( funding_redeemscript . as_bytes ( ) . to_vec ( ) ) ;
}
pub fn without_valid_witness ( & self ) -> & Transaction { & self . tx }
pub fn with_valid_witness ( & self ) -> & Transaction {
assert! ( self . has_local_sig ( ) ) ;
& self . tx
}
}
impl PartialEq for LocalCommitmentTransaction {
// We dont care whether we are signed in equality comparison
fn eq ( & self , o : & Self ) -> bool {
self . txid ( ) = = o . txid ( )
}
}
impl Writeable for LocalCommitmentTransaction {
fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , ::std ::io ::Error > {
if let Err ( e ) = self . tx . consensus_encode ( & mut WriterWriteAdaptor ( writer ) ) {
match e {
encode ::Error ::Io ( e ) = > return Err ( e ) ,
_ = > panic! ( " local tx must have been well-formed! " ) ,
}
}
Ok ( ( ) )
}
}
impl < R : ::std ::io ::Read > Readable < R > for LocalCommitmentTransaction {
fn read ( reader : & mut R ) -> Result < Self , DecodeError > {
let tx = match Transaction ::consensus_decode ( reader . by_ref ( ) ) {
Ok ( tx ) = > tx ,
Err ( e ) = > match e {
encode ::Error ::Io ( ioe ) = > return Err ( DecodeError ::Io ( ioe ) ) ,
_ = > return Err ( DecodeError ::InvalidValue ) ,
} ,
} ;
if tx . input . len ( ) ! = 1 {
// Ensure tx didn't hit the 0-input ambiguity case.
return Err ( DecodeError ::InvalidValue ) ;
}
Ok ( Self { tx } )
}
}
2020-02-07 16:05:24 -05:00
#[ cfg(test) ]
mod tests {
use super ::CounterpartyCommitmentSecrets ;
use hex ;
#[ test ]
fn test_per_commitment_storage ( ) {
// Test vectors from BOLT 3:
let mut secrets : Vec < [ u8 ; 32 ] > = Vec ::new ( ) ;
let mut monitor ;
macro_rules ! test_secrets {
( ) = > {
let mut idx = 281474976710655 ;
for secret in secrets . iter ( ) {
assert_eq! ( monitor . get_secret ( idx ) . unwrap ( ) , * secret ) ;
idx - = 1 ;
}
assert_eq! ( monitor . get_min_seen_secret ( ) , idx + 1 ) ;
assert! ( monitor . get_secret ( idx ) . is_none ( ) ) ;
} ;
}
{
// insert_secret correct sequence
monitor = CounterpartyCommitmentSecrets ::new ( ) ;
secrets . clear ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710655 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710654 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710653 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710652 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710651 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710650 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710649 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710648 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
}
{
// insert_secret #1 incorrect
monitor = CounterpartyCommitmentSecrets ::new ( ) ;
secrets . clear ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710655 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 " ) . unwrap ( ) ) ;
assert! ( monitor . provide_secret ( 281474976710654 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . is_err ( ) ) ;
}
{
// insert_secret #2 incorrect (#1 derived from incorrect)
monitor = CounterpartyCommitmentSecrets ::new ( ) ;
secrets . clear ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710655 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710654 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710653 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 " ) . unwrap ( ) ) ;
assert! ( monitor . provide_secret ( 281474976710652 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . is_err ( ) ) ;
}
{
// insert_secret #3 incorrect
monitor = CounterpartyCommitmentSecrets ::new ( ) ;
secrets . clear ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710655 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710654 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710653 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 " ) . unwrap ( ) ) ;
assert! ( monitor . provide_secret ( 281474976710652 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . is_err ( ) ) ;
}
{
// insert_secret #4 incorrect (1,2,3 derived from incorrect)
monitor = CounterpartyCommitmentSecrets ::new ( ) ;
secrets . clear ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710655 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710654 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710653 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " ba65d7b0ef55a3ba300d4e87af29868f394f8f138d78a7011669c79b37b936f4 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710652 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710651 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710650 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710649 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17 " ) . unwrap ( ) ) ;
assert! ( monitor . provide_secret ( 281474976710648 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . is_err ( ) ) ;
}
{
// insert_secret #5 incorrect
monitor = CounterpartyCommitmentSecrets ::new ( ) ;
secrets . clear ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710655 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710654 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710653 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710652 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710651 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2 " ) . unwrap ( ) ) ;
assert! ( monitor . provide_secret ( 281474976710650 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . is_err ( ) ) ;
}
{
// insert_secret #6 incorrect (5 derived from incorrect)
monitor = CounterpartyCommitmentSecrets ::new ( ) ;
secrets . clear ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710655 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710654 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710653 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710652 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710651 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " b7e76a83668bde38b373970155c868a653304308f9896692f904a23731224bb1 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710650 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710649 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17 " ) . unwrap ( ) ) ;
assert! ( monitor . provide_secret ( 281474976710648 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . is_err ( ) ) ;
}
{
// insert_secret #7 incorrect
monitor = CounterpartyCommitmentSecrets ::new ( ) ;
secrets . clear ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710655 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710654 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710653 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710652 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710651 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710650 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " e7971de736e01da8ed58b94c2fc216cb1dca9e326f3a96e7194fe8ea8af6c0a3 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710649 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17 " ) . unwrap ( ) ) ;
assert! ( monitor . provide_secret ( 281474976710648 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . is_err ( ) ) ;
}
{
// insert_secret #8 incorrect
monitor = CounterpartyCommitmentSecrets ::new ( ) ;
secrets . clear ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710655 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710654 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710653 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710652 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710651 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " 969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710650 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32 " ) . unwrap ( ) ) ;
monitor . provide_secret ( 281474976710649 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . unwrap ( ) ;
test_secrets! ( ) ;
secrets . push ( [ 0 ; 32 ] ) ;
secrets . last_mut ( ) . unwrap ( ) [ 0 .. 32 ] . clone_from_slice ( & hex ::decode ( " a7efbc61aac46d34f77778bac22c8a20c6a46ca460addc49009bda875ec88fa4 " ) . unwrap ( ) ) ;
assert! ( monitor . provide_secret ( 281474976710648 , secrets . last ( ) . unwrap ( ) . clone ( ) ) . is_err ( ) ) ;
}
}
}