@@ -7785,4 +7785,189 @@ mod tests {
7785
7785
} ;
7786
7786
check_spends ! ( spend_tx, node_txn[ 0 ] . clone( ) ) ;
7787
7787
}
7788
+
7789
+ #[ test]
7790
+ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx ( ) {
7791
+ let nodes = create_network ( 2 ) ;
7792
+
7793
+ // Create some initial channels
7794
+ let chan_1 = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
7795
+
7796
+ let payment_preimage = route_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 3000000 ) . 0 ;
7797
+ let revoked_local_txn = nodes[ 0 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_1. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
7798
+ assert_eq ! ( revoked_local_txn[ 0 ] . input. len( ) , 1 ) ;
7799
+ assert_eq ! ( revoked_local_txn[ 0 ] . input[ 0 ] . previous_output. txid, chan_1. 3 . txid( ) ) ;
7800
+
7801
+ claim_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , payment_preimage) ;
7802
+
7803
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
7804
+ // A will generate HTLC-Timeout from revoked commitment tx
7805
+ nodes[ 0 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) ] } , 1 ) ;
7806
+ let events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
7807
+ match events[ 0 ] {
7808
+ MessageSendEvent :: BroadcastChannelUpdate { .. } => { } ,
7809
+ _ => panic ! ( "Unexpected event" ) ,
7810
+ }
7811
+ let revoked_htlc_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
7812
+ assert_eq ! ( revoked_htlc_txn. len( ) , 2 ) ;
7813
+ assert_eq ! ( revoked_htlc_txn[ 0 ] . input. len( ) , 1 ) ;
7814
+ assert_eq ! ( revoked_htlc_txn[ 0 ] . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) , 133 ) ;
7815
+ check_spends ! ( revoked_htlc_txn[ 0 ] , revoked_local_txn[ 0 ] . clone( ) ) ;
7816
+
7817
+ // B will generate justice tx from A's revoked commitment/HTLC tx
7818
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) , revoked_htlc_txn[ 0 ] . clone( ) ] } , 1 ) ;
7819
+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
7820
+ match events[ 0 ] {
7821
+ MessageSendEvent :: BroadcastChannelUpdate { .. } => { } ,
7822
+ _ => panic ! ( "Unexpected event" ) ,
7823
+ }
7824
+
7825
+ let node_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
7826
+ assert_eq ! ( node_txn. len( ) , 4 ) ;
7827
+ assert_eq ! ( node_txn[ 3 ] . input. len( ) , 1 ) ;
7828
+ check_spends ! ( node_txn[ 3 ] , revoked_htlc_txn[ 0 ] . clone( ) ) ;
7829
+
7830
+ let events = nodes[ 1 ] . chan_monitor . simple_monitor . get_and_clear_pending_events ( ) ;
7831
+ // Check B's ChannelMonitor was able to generate the right spendable output descriptor
7832
+ let spend_tx = match events[ 1 ] {
7833
+ Event :: SpendableOutputs { ref outputs } => {
7834
+ match outputs[ 1 ] {
7835
+ SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
7836
+ let secp_ctx = Secp256k1 :: new ( ) ;
7837
+ let input = TxIn {
7838
+ previous_output : outpoint. clone ( ) ,
7839
+ script_sig : Script :: new ( ) ,
7840
+ sequence : 0 ,
7841
+ witness : Vec :: new ( ) ,
7842
+ } ;
7843
+ let outp = TxOut {
7844
+ script_pubkey : Builder :: new ( ) . push_opcode ( opcodes:: All :: OP_RETURN ) . into_script ( ) ,
7845
+ value : output. value ,
7846
+ } ;
7847
+ let mut spend_tx = Transaction {
7848
+ version : 2 ,
7849
+ lock_time : 0 ,
7850
+ input : vec ! [ input] ,
7851
+ output : vec ! [ outp. clone( ) ] ,
7852
+ } ;
7853
+ let destination_secret = {
7854
+ match ExtendedPrivKey :: new_master ( & secp_ctx, Network :: Testnet , & nodes[ 1 ] . node_seed ) {
7855
+ Ok ( master_key) => {
7856
+ match master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 1 ) ) {
7857
+ Ok ( destination_key) => destination_key,
7858
+ Err ( _) => panic ! ( "Your RNG is busted" ) ,
7859
+ }
7860
+ }
7861
+ Err ( _) => panic ! ( "Your rng is busted" ) ,
7862
+ }
7863
+ } ;
7864
+ let destination_pubkey = ExtendedPubKey :: from_private ( & secp_ctx, & destination_secret) . public_key ;
7865
+ let witness_script = Address :: p2pkh ( & destination_pubkey, Network :: Testnet ) . script_pubkey ( ) ;
7866
+ let sighash = Message :: from_slice ( & bip143:: SighashComponents :: new ( & spend_tx) . sighash_all ( & spend_tx. input [ 0 ] , & witness_script, output. value ) [ ..] ) . unwrap ( ) ;
7867
+ let sig = secp_ctx. sign ( & sighash, & destination_secret. secret_key ) ;
7868
+ spend_tx. input [ 0 ] . witness . push ( sig. serialize_der ( & secp_ctx) . to_vec ( ) ) ;
7869
+ spend_tx. input [ 0 ] . witness [ 0 ] . push ( SigHashType :: All as u8 ) ;
7870
+ spend_tx. input [ 0 ] . witness . push ( destination_pubkey. serialize ( ) . to_vec ( ) ) ;
7871
+ spend_tx
7872
+ } ,
7873
+ _ => panic ! ( "Unexpected event !" ) ,
7874
+ }
7875
+ } ,
7876
+ _ => panic ! ( "Unexpected event !" ) ,
7877
+ } ;
7878
+ check_spends ! ( spend_tx, node_txn[ 3 ] . clone( ) ) ;
7879
+ }
7880
+
7881
+ #[ test]
7882
+ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx ( ) {
7883
+ let nodes = create_network ( 2 ) ;
7884
+
7885
+ // Create some initial channels
7886
+ let chan_1 = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) ;
7887
+
7888
+ let payment_preimage = route_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , 3000000 ) . 0 ;
7889
+ let revoked_local_txn = nodes[ 1 ] . node . channel_state . lock ( ) . unwrap ( ) . by_id . get ( & chan_1. 2 ) . unwrap ( ) . last_local_commitment_txn . clone ( ) ;
7890
+ assert_eq ! ( revoked_local_txn[ 0 ] . input. len( ) , 1 ) ;
7891
+ assert_eq ! ( revoked_local_txn[ 0 ] . input[ 0 ] . previous_output. txid, chan_1. 3 . txid( ) ) ;
7892
+
7893
+ claim_payment ( & nodes[ 0 ] , & vec ! ( & nodes[ 1 ] ) [ ..] , payment_preimage) ;
7894
+
7895
+ let header = BlockHeader { version : 0x20000000 , prev_blockhash : Default :: default ( ) , merkle_root : Default :: default ( ) , time : 42 , bits : 42 , nonce : 42 } ;
7896
+ // B will generate HTLC-Success from revoked commitment tx
7897
+ nodes[ 1 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) ] } , 1 ) ;
7898
+ let events = nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
7899
+ match events[ 0 ] {
7900
+ MessageSendEvent :: BroadcastChannelUpdate { .. } => { } ,
7901
+ _ => panic ! ( "Unexpected event" ) ,
7902
+ }
7903
+ let revoked_htlc_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
7904
+
7905
+ assert_eq ! ( revoked_htlc_txn. len( ) , 2 ) ;
7906
+ assert_eq ! ( revoked_htlc_txn[ 0 ] . input. len( ) , 1 ) ;
7907
+ assert_eq ! ( revoked_htlc_txn[ 0 ] . input[ 0 ] . witness. last( ) . unwrap( ) . len( ) , 138 ) ;
7908
+ check_spends ! ( revoked_htlc_txn[ 0 ] , revoked_local_txn[ 0 ] . clone( ) ) ;
7909
+
7910
+ // A will generate justice tx from B's revoked commitment/HTLC tx
7911
+ nodes[ 0 ] . chain_monitor . block_connected_with_filtering ( & Block { header, txdata : vec ! [ revoked_local_txn[ 0 ] . clone( ) , revoked_htlc_txn[ 0 ] . clone( ) ] } , 1 ) ;
7912
+ let events = nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
7913
+ match events[ 0 ] {
7914
+ MessageSendEvent :: BroadcastChannelUpdate { .. } => { } ,
7915
+ _ => panic ! ( "Unexpected event" ) ,
7916
+ }
7917
+
7918
+ let node_txn = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) ;
7919
+ assert_eq ! ( node_txn. len( ) , 4 ) ;
7920
+ assert_eq ! ( node_txn[ 3 ] . input. len( ) , 1 ) ;
7921
+ check_spends ! ( node_txn[ 3 ] , revoked_htlc_txn[ 0 ] . clone( ) ) ;
7922
+
7923
+ let events = nodes[ 0 ] . chan_monitor . simple_monitor . get_and_clear_pending_events ( ) ;
7924
+ // Check A's ChannelMonitor was able to generate the right spendable output descriptor
7925
+ let spend_tx = match events[ 1 ] {
7926
+ Event :: SpendableOutputs { ref outputs } => {
7927
+ match outputs[ 2 ] {
7928
+ SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
7929
+ let secp_ctx = Secp256k1 :: new ( ) ;
7930
+ let input = TxIn {
7931
+ previous_output : outpoint. clone ( ) ,
7932
+ script_sig : Script :: new ( ) ,
7933
+ sequence : 0 ,
7934
+ witness : Vec :: new ( ) ,
7935
+ } ;
7936
+ let outp = TxOut {
7937
+ script_pubkey : Builder :: new ( ) . push_opcode ( opcodes:: All :: OP_RETURN ) . into_script ( ) ,
7938
+ value : output. value ,
7939
+ } ;
7940
+ let mut spend_tx = Transaction {
7941
+ version : 2 ,
7942
+ lock_time : 0 ,
7943
+ input : vec ! [ input] ,
7944
+ output : vec ! [ outp. clone( ) ] ,
7945
+ } ;
7946
+ let destination_secret = {
7947
+ match ExtendedPrivKey :: new_master ( & secp_ctx, Network :: Testnet , & nodes[ 0 ] . node_seed ) {
7948
+ Ok ( master_key) => {
7949
+ match master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 1 ) ) {
7950
+ Ok ( destination_key) => destination_key,
7951
+ Err ( _) => panic ! ( "Your RNG is busted" ) ,
7952
+ }
7953
+ }
7954
+ Err ( _) => panic ! ( "Your rng is busted" ) ,
7955
+ }
7956
+ } ;
7957
+ let destination_pubkey = ExtendedPubKey :: from_private ( & secp_ctx, & destination_secret) . public_key ;
7958
+ let witness_script = Address :: p2pkh ( & destination_pubkey, Network :: Testnet ) . script_pubkey ( ) ;
7959
+ let sighash = Message :: from_slice ( & bip143:: SighashComponents :: new ( & spend_tx) . sighash_all ( & spend_tx. input [ 0 ] , & witness_script, output. value ) [ ..] ) . unwrap ( ) ;
7960
+ let sig = secp_ctx. sign ( & sighash, & destination_secret. secret_key ) ;
7961
+ spend_tx. input [ 0 ] . witness . push ( sig. serialize_der ( & secp_ctx) . to_vec ( ) ) ;
7962
+ spend_tx. input [ 0 ] . witness [ 0 ] . push ( SigHashType :: All as u8 ) ;
7963
+ spend_tx. input [ 0 ] . witness . push ( destination_pubkey. serialize ( ) . to_vec ( ) ) ;
7964
+ spend_tx
7965
+ } ,
7966
+ _ => panic ! ( "Unexpected event !" ) ,
7967
+ }
7968
+ } ,
7969
+ _ => panic ! ( "Unexpected event !" ) ,
7970
+ } ;
7971
+ check_spends ! ( spend_tx, node_txn[ 3 ] . clone( ) ) ;
7972
+ }
7788
7973
}
0 commit comments