@@ -136,6 +136,8 @@ pub enum SpendableOutputDescriptor {
136
136
outpoint : OutPoint ,
137
137
/// The output which is referenced by the given outpoint.
138
138
output : TxOut ,
139
+ /// Key which is used to derive child keys
140
+ channel_keys_id : [ u8 ; 32 ]
139
141
} ,
140
142
/// An output to a P2WSH script which can be spent with a single signature after a CSV delay.
141
143
///
@@ -180,6 +182,7 @@ impl_writeable_tlv_based_enum!(SpendableOutputDescriptor,
180
182
( 0 , StaticOutput ) => {
181
183
( 0 , outpoint, required) ,
182
184
( 2 , output, required) ,
185
+ ( 4 , channel_keys_id, required) ,
183
186
} ,
184
187
;
185
188
( 1 , DelayedPaymentOutput ) ,
@@ -814,8 +817,7 @@ pub struct KeysManager {
814
817
secp_ctx : Secp256k1 < secp256k1:: All > ,
815
818
node_secret : SecretKey ,
816
819
inbound_payment_key : KeyMaterial ,
817
- destination_script : Script ,
818
- shutdown_pubkey : PublicKey ,
820
+ shutdown_pubkey : ExtendedPubKey ,
819
821
channel_master_key : ExtendedPrivKey ,
820
822
channel_child_index : AtomicUsize ,
821
823
@@ -854,17 +856,8 @@ impl KeysManager {
854
856
match ExtendedPrivKey :: new_master ( Network :: Testnet , seed) {
855
857
Ok ( master_key) => {
856
858
let node_secret = master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 0 ) . unwrap ( ) ) . expect ( "Your RNG is busted" ) . private_key . key ;
857
- let destination_script = match master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 1 ) . unwrap ( ) ) {
858
- Ok ( destination_key) => {
859
- let wpubkey_hash = WPubkeyHash :: hash ( & ExtendedPubKey :: from_private ( & secp_ctx, & destination_key) . public_key . to_bytes ( ) ) ;
860
- Builder :: new ( ) . push_opcode ( opcodes:: all:: OP_PUSHBYTES_0 )
861
- . push_slice ( & wpubkey_hash. into_inner ( ) )
862
- . into_script ( )
863
- } ,
864
- Err ( _) => panic ! ( "Your RNG is busted" ) ,
865
- } ;
866
859
let shutdown_pubkey = match master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 2 ) . unwrap ( ) ) {
867
- Ok ( shutdown_key) => ExtendedPubKey :: from_private ( & secp_ctx, & shutdown_key) . public_key . key ,
860
+ Ok ( shutdown_key) => ExtendedPubKey :: from_private ( & secp_ctx, & shutdown_key) ,
868
861
Err ( _) => panic ! ( "Your RNG is busted" ) ,
869
862
} ;
870
863
let channel_master_key = master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 3 ) . unwrap ( ) ) . expect ( "Your RNG is busted" ) ;
@@ -882,8 +875,6 @@ impl KeysManager {
882
875
secp_ctx,
883
876
node_secret,
884
877
inbound_payment_key : KeyMaterial ( inbound_pmt_key_bytes) ,
885
-
886
- destination_script,
887
878
shutdown_pubkey,
888
879
889
880
channel_master_key,
@@ -1000,7 +991,7 @@ impl KeysManager {
1000
991
input_value += descriptor. output . value ;
1001
992
if !output_set. insert ( descriptor. outpoint ) { return Err ( ( ) ) ; }
1002
993
} ,
1003
- SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output } => {
994
+ SpendableOutputDescriptor :: StaticOutput { ref outpoint, ref output, .. } => {
1004
995
input. push ( TxIn {
1005
996
previous_output : outpoint. into_bitcoin_outpoint ( ) ,
1006
997
script_sig : Script :: new ( ) ,
@@ -1043,12 +1034,25 @@ impl KeysManager {
1043
1034
}
1044
1035
spend_tx. input [ input_idx] . witness = keys_cache. as_ref ( ) . unwrap ( ) . 0 . sign_dynamic_p2wsh_input ( & spend_tx, input_idx, & descriptor, & secp_ctx) ?;
1045
1036
} ,
1046
- SpendableOutputDescriptor :: StaticOutput { ref output, .. } => {
1047
- let derivation_idx = if output. script_pubkey == self . destination_script {
1037
+ SpendableOutputDescriptor :: StaticOutput { ref output, channel_keys_id, .. } => {
1038
+ let derivation_idx = byte_utils:: slice_to_be64 ( & channel_keys_id[ 0 ..8 ] ) ;
1039
+ let destination_script = match self . channel_master_key . ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( derivation_idx as u32 ) . expect ( "key space exhausted" ) ) {
1040
+ Ok ( destination_key) => {
1041
+ let wpubkey_hash = WPubkeyHash :: hash ( & ExtendedPubKey :: from_private ( & secp_ctx, & destination_key) . public_key . to_bytes ( ) ) ;
1042
+ Builder :: new ( ) . push_opcode ( opcodes:: all:: OP_PUSHBYTES_0 )
1043
+ . push_slice ( & wpubkey_hash. into_inner ( ) )
1044
+ . into_script ( )
1045
+ } ,
1046
+ Err ( _) => panic ! ( "Your RNG is busted" ) ,
1047
+ } ;
1048
+
1049
+
1050
+ let derivation_idx = if output. script_pubkey == destination_script {
1048
1051
1
1049
1052
} else {
1050
1053
2
1051
1054
} ;
1055
+
1052
1056
let secret = {
1053
1057
// Note that when we aren't serializing the key, network doesn't matter
1054
1058
match ExtendedPrivKey :: new_master ( Network :: Testnet , & self . seed ) {
@@ -1063,7 +1067,7 @@ impl KeysManager {
1063
1067
} ;
1064
1068
let pubkey = ExtendedPubKey :: from_private ( & secp_ctx, & secret) . public_key ;
1065
1069
if derivation_idx == 2 {
1066
- assert_eq ! ( pubkey. key, self . shutdown_pubkey) ;
1070
+ assert_eq ! ( pubkey. key, self . shutdown_pubkey. public_key . key ) ;
1067
1071
}
1068
1072
let witness_script = bitcoin:: Address :: p2pkh ( & pubkey, Network :: Testnet ) . script_pubkey ( ) ;
1069
1073
let payment_script = bitcoin:: Address :: p2wpkh ( & pubkey, Network :: Testnet ) . expect ( "uncompressed key found" ) . script_pubkey ( ) ;
@@ -1101,11 +1105,11 @@ impl KeysInterface for KeysManager {
1101
1105
}
1102
1106
1103
1107
fn get_destination_script ( & self ) -> Script {
1104
- self . destination_script . clone ( )
1108
+ bitcoin :: Address :: p2wpkh ( & :: bitcoin :: PublicKey { compressed : true , key : self . shutdown_pubkey . public_key . key } , Network :: Testnet ) . unwrap ( ) . script_pubkey ( )
1105
1109
}
1106
1110
1107
1111
fn get_shutdown_scriptpubkey ( & self ) -> ShutdownScript {
1108
- ShutdownScript :: new_p2wpkh_from_pubkey ( self . shutdown_pubkey . clone ( ) )
1112
+ ShutdownScript :: new_p2wpkh_from_pubkey ( self . shutdown_pubkey . public_key . key . clone ( ) )
1109
1113
}
1110
1114
1111
1115
fn get_channel_signer ( & self , _inbound : bool , channel_value_satoshis : u64 ) -> Self :: Signer {
0 commit comments