7
7
//!
8
8
9
9
use bitcoin:: blockdata:: transaction:: OutPoint ;
10
- use bitcoin:: blockdata:: script:: Script ;
10
+ use bitcoin:: blockdata:: script:: { Script , Builder } ;
11
+ use bitcoin:: blockdata:: opcodes;
12
+ use bitcoin:: blockdata:: constants:: genesis_block;
13
+ use bitcoin:: network:: constants:: Network ;
14
+ use bitcoin:: network:: serialize:: BitcoinHash ;
15
+ use bitcoin:: util:: hash:: Sha256dHash ;
16
+ use bitcoin:: util:: bip32:: { ExtendedPrivKey , ExtendedPubKey , ChildNumber } ;
11
17
12
18
use secp256k1:: key:: { SecretKey , PublicKey } ;
13
19
use secp256k1:: Secp256k1 ;
@@ -17,6 +23,9 @@ use crypto::hkdf::{hkdf_extract,hkdf_expand};
17
23
18
24
use util:: events;
19
25
use util:: sha2:: Sha256 ;
26
+ use util:: logger:: Logger ;
27
+
28
+ use std:: sync:: Arc ;
20
29
21
30
/// A trait to describe a wallet which sould receive data to be able to spend onchain outputs
22
31
/// fron a lightning channel
@@ -155,3 +164,88 @@ impl ChannelKeys {
155
164
} )
156
165
}
157
166
}
167
+
168
+ /// Utility for storing/deriving lightning keys materials
169
+ pub struct KeysManager {
170
+ genesis_hash : Sha256dHash ,
171
+ secp_ctx : Secp256k1 < secp256k1:: All > ,
172
+ master_key : SecretKey ,
173
+ node_secret : SecretKey ,
174
+ destination_script : Script ,
175
+ shutdown_pubkey : PublicKey ,
176
+ channel_master_seed : ExtendedPrivKey ,
177
+ current_channel_index : u32 ,
178
+
179
+ logger : Arc < Logger > ,
180
+ }
181
+
182
+ impl KeysManager {
183
+ /// Constructs and empty KeysManager
184
+ pub fn new ( seed : & [ u8 ; 32 ] , network : Network , logger : Arc < Logger > ) -> Option < KeysManager > {
185
+ let secp_ctx = Secp256k1 :: new ( ) ;
186
+ match ExtendedPrivKey :: new_master ( & secp_ctx, network. clone ( ) , seed) {
187
+ Ok ( master_key) => {
188
+ let node_secret = match master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 0 ) ) {
189
+ Ok ( node_secret) => node_secret. secret_key ,
190
+ Err ( _) => return None ,
191
+ } ;
192
+ let destination_script = match master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 1 ) ) {
193
+ Ok ( destination_key) => Builder :: new ( ) . push_slice ( & ExtendedPubKey :: from_private ( & secp_ctx, & destination_key) . public_key . serialize ( ) [ ..] )
194
+ . push_opcode ( opcodes:: All :: OP_CHECKSIG )
195
+ . into_script ( ) ,
196
+ Err ( _) => return None ,
197
+ } ;
198
+ let shutdown_pubkey = match master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 2 ) ) {
199
+ Ok ( shutdown_key) => ExtendedPubKey :: from_private ( & secp_ctx, & shutdown_key) . public_key ,
200
+ Err ( _) => return None ,
201
+ } ;
202
+ let channel_master_seed = match master_key. ckd_priv ( & secp_ctx, ChildNumber :: from_hardened_idx ( 3 ) ) {
203
+ Ok ( channel_master_key) => channel_master_key,
204
+ Err ( _) => return None ,
205
+ } ;
206
+ Some ( KeysManager {
207
+ genesis_hash : genesis_block ( network) . header . bitcoin_hash ( ) ,
208
+ secp_ctx,
209
+ master_key : master_key. secret_key ,
210
+ node_secret,
211
+ destination_script,
212
+ shutdown_pubkey,
213
+ channel_master_seed,
214
+ current_channel_index : 0 ,
215
+
216
+ logger,
217
+ } )
218
+ } ,
219
+ Err ( _) => None ,
220
+ } ;
221
+ None
222
+ }
223
+ }
224
+
225
+ impl KeysInterface for KeysManager {
226
+ fn get_node_secret ( & self ) -> SecretKey {
227
+ self . node_secret . clone ( )
228
+ }
229
+
230
+ fn get_destination_script ( & self ) -> Script {
231
+ self . destination_script . clone ( )
232
+ }
233
+
234
+ fn get_shutdown_pubkey ( & self ) -> PublicKey {
235
+ self . shutdown_pubkey . clone ( )
236
+ }
237
+
238
+ fn get_channel_keys ( & mut self ) -> Option < ChannelKeys > {
239
+ if let Ok ( channel_key) = self . channel_master_seed . ckd_priv ( & self . secp_ctx , ChildNumber :: Hardened { index : self . current_channel_index } ) {
240
+ let channel_pubkey = ExtendedPubKey :: from_private ( & self . secp_ctx , & channel_key) ;
241
+ let mut seed = [ 0 ; 32 ] ;
242
+ for ( arr, slice) in seed. iter_mut ( ) . zip ( ( & channel_pubkey. public_key . serialize ( ) [ 0 ..32 ] ) . iter ( ) ) {
243
+ * arr = * slice;
244
+ }
245
+ if let Ok ( channel_keys) = ChannelKeys :: new_from_seed ( & seed) {
246
+ return Some ( channel_keys) ;
247
+ }
248
+ }
249
+ None
250
+ }
251
+ }
0 commit comments