Skip to content

Commit 177956e

Browse files
author
Antoine Riard
committed
Implement KeysInterface for KeysManager util
1 parent f317219 commit 177956e

File tree

1 file changed

+95
-1
lines changed

1 file changed

+95
-1
lines changed

src/chain/keysinterface.rs

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77
//!
88
99
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};
1117

1218
use secp256k1::key::{SecretKey, PublicKey};
1319
use secp256k1::Secp256k1;
@@ -17,6 +23,9 @@ use crypto::hkdf::{hkdf_extract,hkdf_expand};
1723

1824
use util::events;
1925
use util::sha2::Sha256;
26+
use util::logger::Logger;
27+
28+
use std::sync::Arc;
2029

2130
/// A trait to describe a wallet which sould receive data to be able to spend onchain outputs
2231
/// fron a lightning channel
@@ -155,3 +164,88 @@ impl ChannelKeys {
155164
})
156165
}
157166
}
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

Comments
 (0)