@@ -342,6 +342,7 @@ struct LocalSignedTx {
342
342
htlc_outputs : Vec < ( HTLCOutputInCommitment , Option < ( Signature , Signature ) > , Option < HTLCSource > ) > ,
343
343
}
344
344
345
+ #[ derive( PartialEq ) ]
345
346
enum InputDescriptors {
346
347
RevokedOfferedHTLC ,
347
348
RevokedReceivedHTLC ,
@@ -2274,13 +2275,19 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
2274
2275
2275
2276
#[ cfg( test) ]
2276
2277
mod tests {
2277
- use bitcoin:: blockdata:: script:: Script ;
2278
- use bitcoin:: blockdata:: transaction:: Transaction ;
2278
+ use bitcoin:: blockdata:: script:: { Script , Builder } ;
2279
+ use bitcoin:: blockdata:: opcodes;
2280
+ use bitcoin:: blockdata:: transaction:: { Transaction , TxIn , TxOut , SigHashType } ;
2281
+ use bitcoin:: blockdata:: transaction:: OutPoint as BitcoinOutPoint ;
2282
+ use bitcoin:: util:: bip143;
2279
2283
use bitcoin_hashes:: Hash ;
2280
2284
use bitcoin_hashes:: sha256:: Hash as Sha256 ;
2285
+ use bitcoin_hashes:: sha256d:: Hash as Sha256dHash ;
2286
+ use bitcoin_hashes:: hex:: FromHex ;
2281
2287
use hex;
2282
2288
use ln:: channelmanager:: { PaymentPreimage , PaymentHash } ;
2283
- use ln:: channelmonitor:: ChannelMonitor ;
2289
+ use ln:: channelmonitor:: { ChannelMonitor , InputDescriptors } ;
2290
+ use ln:: chan_utils;
2284
2291
use ln:: chan_utils:: { HTLCOutputInCommitment , TxCreationKeys } ;
2285
2292
use util:: test_utils:: TestLogger ;
2286
2293
use secp256k1:: key:: { SecretKey , PublicKey } ;
@@ -2757,5 +2764,117 @@ mod tests {
2757
2764
test_preimages_exist ! ( & preimages[ 0 ..5 ] , monitor) ;
2758
2765
}
2759
2766
2767
+ #[ test]
2768
+ fn test_claim_txn_weight_computation ( ) {
2769
+ // We test Claim txn weight, knowing that we want expected weigth and
2770
+ // not actual case to avoid sigs and time-lock delays hell variances.
2771
+
2772
+ let secp_ctx = Secp256k1 :: new ( ) ;
2773
+ let privkey = SecretKey :: from_slice ( & hex:: decode ( "0101010101010101010101010101010101010101010101010101010101010101" ) . unwrap ( ) [ ..] ) . unwrap ( ) ;
2774
+ let pubkey = PublicKey :: from_secret_key ( & secp_ctx, & privkey) ;
2775
+ let mut sum_actual_sigs: u64 = 0 ;
2776
+
2777
+ macro_rules! sign_input {
2778
+ ( $sighash_parts: expr, $input: expr, $idx: expr, $amount: expr, $input_type: expr, $sum_actual_sigs: expr) => {
2779
+ let htlc = HTLCOutputInCommitment {
2780
+ offered: if * $input_type == InputDescriptors :: RevokedOfferedHTLC || * $input_type == InputDescriptors :: OfferedHTLC { true } else { false } ,
2781
+ amount_msat: 0 ,
2782
+ cltv_expiry: 2 << 16 ,
2783
+ payment_hash: PaymentHash ( [ 1 ; 32 ] ) ,
2784
+ transaction_output_index: Some ( $idx) ,
2785
+ } ;
2786
+ let redeem_script = if * $input_type == InputDescriptors :: RevokedOutput { chan_utils:: get_revokeable_redeemscript( & pubkey, 256 , & pubkey) } else { chan_utils:: get_htlc_redeemscript_with_explicit_keys( & htlc, & pubkey, & pubkey, & pubkey) } ;
2787
+ let sighash = hash_to_message!( & $sighash_parts. sighash_all( & $input, & redeem_script, $amount) [ ..] ) ;
2788
+ let sig = secp_ctx. sign( & sighash, & privkey) ;
2789
+ $input. witness. push( sig. serialize_der( ) . to_vec( ) ) ;
2790
+ $input. witness[ 0 ] . push( SigHashType :: All as u8 ) ;
2791
+ sum_actual_sigs += $input. witness[ 0 ] . len( ) as u64 ;
2792
+ if * $input_type == InputDescriptors :: RevokedOutput {
2793
+ $input. witness. push( vec!( 1 ) ) ;
2794
+ } else if * $input_type == InputDescriptors :: RevokedOfferedHTLC || * $input_type == InputDescriptors :: RevokedReceivedHTLC {
2795
+ $input. witness. push( pubkey. clone( ) . serialize( ) . to_vec( ) ) ;
2796
+ } else if * $input_type == InputDescriptors :: ReceivedHTLC {
2797
+ $input. witness. push( vec![ 0 ] ) ;
2798
+ } else {
2799
+ $input. witness. push( PaymentPreimage ( [ 1 ; 32 ] ) . 0 . to_vec( ) ) ;
2800
+ }
2801
+ $input. witness. push( redeem_script. into_bytes( ) ) ;
2802
+ println!( "witness[0] {}" , $input. witness[ 0 ] . len( ) ) ;
2803
+ println!( "witness[1] {}" , $input. witness[ 1 ] . len( ) ) ;
2804
+ println!( "witness[2] {}" , $input. witness[ 2 ] . len( ) ) ;
2805
+ }
2806
+ }
2807
+
2808
+ let script_pubkey = Builder :: new ( ) . push_opcode ( opcodes:: all:: OP_RETURN ) . into_script ( ) ;
2809
+ let txid = Sha256dHash :: from_hex ( "56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d" ) . unwrap ( ) ;
2810
+
2811
+ // Justice tx with 1 to_local, 2 revoked offered HTLCs, 1 revoked received HTLCs
2812
+ let mut claim_tx = Transaction { version : 0 , lock_time : 0 , input : Vec :: new ( ) , output : Vec :: new ( ) } ;
2813
+ for i in 0 ..4 {
2814
+ claim_tx. input . push ( TxIn {
2815
+ previous_output : BitcoinOutPoint {
2816
+ txid,
2817
+ vout : i,
2818
+ } ,
2819
+ script_sig : Script :: new ( ) ,
2820
+ sequence : 0xfffffffd ,
2821
+ witness : Vec :: new ( ) ,
2822
+ } ) ;
2823
+ }
2824
+ claim_tx. output . push ( TxOut {
2825
+ script_pubkey : script_pubkey. clone ( ) ,
2826
+ value : 0 ,
2827
+ } ) ;
2828
+ let base_weight = claim_tx. get_weight ( ) + 2 ; // segwit flag, not added because lack of witness input at this step
2829
+ let sighash_parts = bip143:: SighashComponents :: new ( & claim_tx) ;
2830
+ let inputs_des = vec ! [ InputDescriptors :: RevokedOutput , InputDescriptors :: RevokedOfferedHTLC , InputDescriptors :: RevokedOfferedHTLC , InputDescriptors :: RevokedReceivedHTLC ] ;
2831
+ for ( idx, inp) in claim_tx. input . iter_mut ( ) . zip ( inputs_des. iter ( ) ) . enumerate ( ) {
2832
+ sign_input ! ( sighash_parts, inp. 0 , idx as u32 , 0 , inp. 1 , sum_actual_sigs) ;
2833
+ }
2834
+ assert_eq ! ( base_weight + ChannelMonitor :: get_witnesses_weight( & inputs_des) , claim_tx. get_weight( ) + /* max_length_sig */ ( 73 * inputs_des. len( ) as u64 - sum_actual_sigs) ) ;
2835
+
2836
+ // Claim tx with 1 offered HTLCs, 3 received HTLCs
2837
+ claim_tx. input . clear ( ) ;
2838
+ sum_actual_sigs = 0 ;
2839
+ for i in 0 ..4 {
2840
+ claim_tx. input . push ( TxIn {
2841
+ previous_output : BitcoinOutPoint {
2842
+ txid,
2843
+ vout : i,
2844
+ } ,
2845
+ script_sig : Script :: new ( ) ,
2846
+ sequence : 0xfffffffd ,
2847
+ witness : Vec :: new ( ) ,
2848
+ } ) ;
2849
+ }
2850
+ let base_weight = claim_tx. get_weight ( ) + 2 ;
2851
+ let sighash_parts = bip143:: SighashComponents :: new ( & claim_tx) ;
2852
+ let inputs_des = vec ! [ InputDescriptors :: OfferedHTLC , InputDescriptors :: ReceivedHTLC , InputDescriptors :: ReceivedHTLC , InputDescriptors :: ReceivedHTLC ] ;
2853
+ for ( idx, inp) in claim_tx. input . iter_mut ( ) . zip ( inputs_des. iter ( ) ) . enumerate ( ) {
2854
+ sign_input ! ( sighash_parts, inp. 0 , idx as u32 , 0 , inp. 1 , sum_actual_sigs) ;
2855
+ }
2856
+ assert_eq ! ( base_weight + ChannelMonitor :: get_witnesses_weight( & inputs_des) , claim_tx. get_weight( ) + /* max_length_sig */ ( 73 * inputs_des. len( ) as u64 - sum_actual_sigs) ) ;
2857
+
2858
+ // Justice tx with 1 revoked HTLC-Success tx output
2859
+ claim_tx. input . clear ( ) ;
2860
+ sum_actual_sigs = 0 ;
2861
+ claim_tx. input . push ( TxIn {
2862
+ previous_output : BitcoinOutPoint {
2863
+ txid,
2864
+ vout : 0 ,
2865
+ } ,
2866
+ script_sig : Script :: new ( ) ,
2867
+ sequence : 0xfffffffd ,
2868
+ witness : Vec :: new ( ) ,
2869
+ } ) ;
2870
+ let base_weight = claim_tx. get_weight ( ) + 2 ;
2871
+ let sighash_parts = bip143:: SighashComponents :: new ( & claim_tx) ;
2872
+ let inputs_des = vec ! [ InputDescriptors :: RevokedOutput ] ;
2873
+ for ( idx, inp) in claim_tx. input . iter_mut ( ) . zip ( inputs_des. iter ( ) ) . enumerate ( ) {
2874
+ sign_input ! ( sighash_parts, inp. 0 , idx as u32 , 0 , inp. 1 , sum_actual_sigs) ;
2875
+ }
2876
+ assert_eq ! ( base_weight + ChannelMonitor :: get_witnesses_weight( & inputs_des) , claim_tx. get_weight( ) + /* max_length_isg */ ( 73 * inputs_des. len( ) as u64 - sum_actual_sigs) ) ;
2877
+ }
2878
+
2760
2879
// Further testing is done in the ChannelManager integration tests.
2761
2880
}
0 commit comments