Skip to content

Commit 6d5dc6c

Browse files
Antoine RiardTheBlueMatt
Antoine Riard
authored andcommitted
Implement KeysInterface for KeysManager util
1 parent d33cb3c commit 6d5dc6c

File tree

1 file changed

+86
-1
lines changed

1 file changed

+86
-1
lines changed

src/chain/keysinterface.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,22 @@
33
//! on-chain output which is theirs.
44
55
use bitcoin::blockdata::transaction::{OutPoint, TxOut};
6-
use bitcoin::blockdata::script::Script;
6+
use bitcoin::blockdata::script::{Script, Builder};
7+
use bitcoin::blockdata::opcodes;
8+
use bitcoin::network::constants::Network;
9+
use bitcoin::util::hash::Hash160;
10+
use bitcoin::util::bip32::{ExtendedPrivKey, ExtendedPubKey, ChildNumber};
711

812
use secp256k1::key::{SecretKey, PublicKey};
913
use secp256k1::Secp256k1;
14+
use secp256k1;
1015

1116
use crypto::hkdf::{hkdf_extract,hkdf_expand};
1217

1318
use util::sha2::Sha256;
19+
use util::logger::Logger;
20+
21+
use std::sync::Arc;
1422

1523
/// When on-chain outputs are created by rust-lightning an event is generated which informs the
1624
/// user thereof. This enum describes the format of the output and provides the OutPoint.
@@ -117,3 +125,80 @@ impl ChannelKeys {
117125
}
118126
}
119127
}
128+
129+
/// Simple KeysInterface implementor that takes a 32-byte seed for use as a BIP 32 extended key
130+
/// and derives keys from that.
131+
///
132+
/// Your node_id is seed/0'
133+
/// ChannelMonitor closes may use seed/1'
134+
/// Cooperative closes may use seed/2'
135+
/// The two close keys may be needed to claim on-chain funds!
136+
pub struct KeysManager {
137+
secp_ctx: Secp256k1<secp256k1::All>,
138+
node_secret: SecretKey,
139+
destination_script: Script,
140+
shutdown_pubkey: PublicKey,
141+
channel_master_key: ExtendedPrivKey,
142+
143+
logger: Arc<Logger>,
144+
}
145+
146+
impl KeysManager {
147+
/// Constructs a KeysManager from a 32-byte seed. If the seed is in some way biased (eg your
148+
/// RNG is busted) this may panic.
149+
pub fn new(seed: &[u8; 32], network: Network, logger: Arc<Logger>) -> KeysManager {
150+
let secp_ctx = Secp256k1::new();
151+
match ExtendedPrivKey::new_master(&secp_ctx, network.clone(), seed) {
152+
Ok(master_key) => {
153+
let node_secret = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(0)).expect("Your RNG is busted").secret_key;
154+
let destination_script = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(1)) {
155+
Ok(destination_key) => {
156+
let pubkey_hash160 = Hash160::from_data(&ExtendedPubKey::from_private(&secp_ctx, &destination_key).public_key.serialize()[..]);
157+
Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0)
158+
.push_slice(pubkey_hash160.as_bytes())
159+
.into_script()
160+
},
161+
Err(_) => panic!("Your RNG is busted"),
162+
};
163+
let shutdown_pubkey = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(2)) {
164+
Ok(shutdown_key) => ExtendedPubKey::from_private(&secp_ctx, &shutdown_key).public_key,
165+
Err(_) => panic!("Your RNG is busted"),
166+
};
167+
let channel_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3)).expect("Your RNG is busted");
168+
KeysManager {
169+
secp_ctx,
170+
node_secret,
171+
destination_script,
172+
shutdown_pubkey,
173+
channel_master_key,
174+
175+
logger,
176+
}
177+
},
178+
Err(_) => panic!("Your rng is busted"),
179+
}
180+
}
181+
}
182+
183+
impl KeysInterface for KeysManager {
184+
fn get_node_secret(&self) -> SecretKey {
185+
self.node_secret.clone()
186+
}
187+
188+
fn get_destination_script(&self) -> Script {
189+
self.destination_script.clone()
190+
}
191+
192+
fn get_shutdown_pubkey(&self) -> PublicKey {
193+
self.shutdown_pubkey.clone()
194+
}
195+
196+
fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys {
197+
let channel_pubkey = ExtendedPubKey::from_private(&self.secp_ctx, &self. channel_master_key);
198+
let mut seed = [0; 32];
199+
for (arr, slice) in seed.iter_mut().zip((&channel_pubkey.public_key.serialize()[0..32]).iter()) {
200+
*arr = *slice;
201+
}
202+
ChannelKeys::new_from_seed(&seed)
203+
}
204+
}

0 commit comments

Comments
 (0)