|
3 | 3 | //! on-chain output which is theirs.
|
4 | 4 |
|
5 | 5 | 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}; |
7 | 11 |
|
8 | 12 | use secp256k1::key::{SecretKey, PublicKey};
|
9 | 13 | use secp256k1::Secp256k1;
|
| 14 | +use secp256k1; |
10 | 15 |
|
11 | 16 | use crypto::hkdf::{hkdf_extract,hkdf_expand};
|
12 | 17 |
|
13 | 18 | use util::sha2::Sha256;
|
| 19 | +use util::logger::Logger; |
| 20 | + |
| 21 | +use std::sync::Arc; |
14 | 22 |
|
15 | 23 | /// When on-chain outputs are created by rust-lightning an event is generated which informs the
|
16 | 24 | /// user thereof. This enum descibes the format of the output and provides the OutPoint.
|
@@ -115,3 +123,79 @@ impl ChannelKeys {
|
115 | 123 | }
|
116 | 124 | }
|
117 | 125 | }
|
| 126 | + |
| 127 | +/// Simple CKeysInterface implementor that takes a 32-byte seed for use as a BIP 32 extended key |
| 128 | +/// and derives keys from that. |
| 129 | +/// |
| 130 | +/// Your node_id is seed/0' |
| 131 | +/// ChannelMonitor closes may use seed/1' |
| 132 | +/// Cooperative closes may use seed/2' |
| 133 | +pub struct KeysManager { |
| 134 | + secp_ctx: Secp256k1<secp256k1::All>, |
| 135 | + node_secret: SecretKey, |
| 136 | + destination_script: Script, |
| 137 | + shutdown_pubkey: PublicKey, |
| 138 | + channel_master_key: ExtendedPrivKey, |
| 139 | + |
| 140 | + logger: Arc<Logger>, |
| 141 | +} |
| 142 | + |
| 143 | +impl KeysManager { |
| 144 | + /// Constructs a KeysManager from a 32-byte seed. If the seed is in some way biased (eg your |
| 145 | + /// RNG is busted) this may panic. |
| 146 | + pub fn new(seed: &[u8; 32], network: Network, logger: Arc<Logger>) -> KeysManager { |
| 147 | + let secp_ctx = Secp256k1::new(); |
| 148 | + match ExtendedPrivKey::new_master(&secp_ctx, network.clone(), seed) { |
| 149 | + Ok(master_key) => { |
| 150 | + let node_secret = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(0)).expect("Your RNG is busted").secret_key; |
| 151 | + let destination_script = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(1)) { |
| 152 | + Ok(destination_key) => { |
| 153 | + let pubkey_hash160 = Hash160::from_data(&ExtendedPubKey::from_private(&secp_ctx, &destination_key).public_key.serialize()[..]); |
| 154 | + Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0) |
| 155 | + .push_slice(pubkey_hash160.as_bytes()) |
| 156 | + .into_script() |
| 157 | + }, |
| 158 | + Err(_) => panic!("Your RNG is busted"), |
| 159 | + }; |
| 160 | + let shutdown_pubkey = match master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(2)) { |
| 161 | + Ok(shutdown_key) => ExtendedPubKey::from_private(&secp_ctx, &shutdown_key).public_key, |
| 162 | + Err(_) => panic!("Your RNG is busted"), |
| 163 | + }; |
| 164 | + let channel_master_key = master_key.ckd_priv(&secp_ctx, ChildNumber::from_hardened_idx(3)).expect("Your RNG is busted"); |
| 165 | + KeysManager { |
| 166 | + secp_ctx, |
| 167 | + node_secret, |
| 168 | + destination_script, |
| 169 | + shutdown_pubkey, |
| 170 | + channel_master_key, |
| 171 | + |
| 172 | + logger, |
| 173 | + } |
| 174 | + }, |
| 175 | + Err(_) => panic!("Your rng is busted"), |
| 176 | + } |
| 177 | + } |
| 178 | +} |
| 179 | + |
| 180 | +impl KeysInterface for KeysManager { |
| 181 | + fn get_node_secret(&self) -> SecretKey { |
| 182 | + self.node_secret.clone() |
| 183 | + } |
| 184 | + |
| 185 | + fn get_destination_script(&self) -> Script { |
| 186 | + self.destination_script.clone() |
| 187 | + } |
| 188 | + |
| 189 | + fn get_shutdown_pubkey(&self) -> PublicKey { |
| 190 | + self.shutdown_pubkey.clone() |
| 191 | + } |
| 192 | + |
| 193 | + fn get_channel_keys(&self, _inbound: bool) -> ChannelKeys { |
| 194 | + let channel_pubkey = ExtendedPubKey::from_private(&self.secp_ctx, &self. channel_master_key); |
| 195 | + let mut seed = [0; 32]; |
| 196 | + for (arr, slice) in seed.iter_mut().zip((&channel_pubkey.public_key.serialize()[0..32]).iter()) { |
| 197 | + *arr = *slice; |
| 198 | + } |
| 199 | + ChannelKeys::new_from_seed(&seed) |
| 200 | + } |
| 201 | +} |
0 commit comments