@@ -190,14 +190,12 @@ impl Derivation for SharedKeyId {
190190/// handling [`GenerateKey`], [`GenerateSharedKey`] and [`Sign`].
191191#[ derive( Clone , Debug ) ]
192192pub struct KeyManager {
193- /// The master 32-bytes seed used to derive all the keys for all the swaps.
194- master_seed : [ u8 ; 32 ] ,
195193 /// The swap identifier used in the derivation.
196194 swap_index : ChildNumber ,
197- /// The master secp256k1 seed .
198- bitcoin_master_key : Secp256k1ExtSecretKey ,
199- /// The master ed25519 seed .
200- monero_master_key : Ed25519ExtSecretKey ,
195+ /// The secp256k1 account key as derived from swap_index .
196+ bitcoin_account_key : Secp256k1ExtSecretKey ,
197+ /// The ed25519 account key as derived from swap_index .
198+ monero_account_key : Ed25519ExtSecretKey ,
201199 /// A list of already derived keys for secp256k1 by derivation path.
202200 bitcoin_derivations : HashMap < DerivationPath , SecretKey > ,
203201 /// A list of already derived monero keys for ed25519 by derivation path.
@@ -206,22 +204,22 @@ pub struct KeyManager {
206204
207205impl Encodable for KeyManager {
208206 fn consensus_encode < W : std:: io:: Write > ( & self , writer : & mut W ) -> Result < usize , std:: io:: Error > {
209- let mut len = self . master_seed . consensus_encode ( writer) ?;
210- len += Into :: < u32 > :: into ( self . swap_index ) . consensus_encode ( writer) ?;
211- // TODO: don't add derivations, but test that key manager encoding is correct modulo cached derivations
207+ let mut len = Into :: < u32 > :: into ( self . swap_index ) . consensus_encode ( writer) ?;
208+ len += self . bitcoin_account_key . consensus_encode ( writer) ?;
209+ len += self . monero_account_key . consensus_encode ( writer ) ? ;
212210 Ok ( len)
213211 }
214212}
215213
216214impl Decodable for KeyManager {
217215 fn consensus_decode < D : std:: io:: Read > ( d : & mut D ) -> Result < Self , consensus:: Error > {
218- let master_seed = Decodable :: consensus_decode ( d) ?;
219216 let swap_index: u32 = Decodable :: consensus_decode ( d) ?;
217+ let bitcoin_account_key = Secp256k1ExtSecretKey :: consensus_decode ( d) ?;
218+ let monero_account_key = Ed25519ExtSecretKey :: consensus_decode ( d) ?;
220219 Ok ( KeyManager {
221- master_seed,
222220 swap_index : ChildNumber :: from ( swap_index) ,
223- bitcoin_master_key : Secp256k1ExtSecretKey :: new_master ( master_seed . as_ref ( ) ) ,
224- monero_master_key : Ed25519ExtSecretKey :: new_master ( master_seed . as_ref ( ) ) ,
221+ bitcoin_account_key ,
222+ monero_account_key ,
225223 bitcoin_derivations : HashMap :: new ( ) ,
226224 monero_derivations : HashMap :: new ( ) ,
227225 } )
@@ -231,16 +229,14 @@ impl Decodable for KeyManager {
231229impl_strict_encoding ! ( KeyManager ) ;
232230
233231impl KeyManager {
234- /// Generate the derivation path of a key, computed as:
235- /// `m/44'/{blockchain}'/{swap_index}'/{key_type}'/{key_idx}'`.
236- pub fn get_derivation_path (
237- & self ,
232+ /// Generate the derivation path of an account key, computed as:
233+ /// `m/44'/{blockchain}'/{swap_index}'`.
234+ pub fn get_account_derivation_path (
238235 blockchain : Blockchain ,
239- key_id : impl Derivation ,
236+ swap_index : ChildNumber ,
240237 ) -> Result < DerivationPath , crypto:: Error > {
241238 let path = blockchain. derivation_path ( ) ?;
242- let path = path. extend ( [ self . swap_index ] ) ;
243- Ok ( path. extend ( & key_id. derivation_path ( ) ?) )
239+ Ok ( path. extend ( [ swap_index] ) )
244240 }
245241
246242 /// Try to retreive the secret key internally if already generated, if the key is not found
@@ -249,7 +245,7 @@ impl KeyManager {
249245 & mut self ,
250246 key_id : impl Derivation ,
251247 ) -> Result < SecretKey , crypto:: Error > {
252- let path = self . get_derivation_path ( Blockchain :: Bitcoin , key_id ) ?;
248+ let path = key_id . derivation_path ( ) ?;
253249 self . bitcoin_derivations
254250 . get ( & path)
255251 // Option<Result<SecretKey, _>>
@@ -258,7 +254,7 @@ impl KeyManager {
258254 // None => || { ... } => Result<SecretKey, crypto::Error>
259255 . unwrap_or_else ( || {
260256 let secp = Secp256k1 :: new ( ) ;
261- match self . bitcoin_master_key . derive_priv ( & secp, & path) {
257+ match self . bitcoin_account_key . derive_priv ( & secp, & path) {
262258 Ok ( key) => {
263259 self . bitcoin_derivations . insert ( path, key. secret_key ) ;
264260 Ok ( key. secret_key )
@@ -274,7 +270,7 @@ impl KeyManager {
274270 & mut self ,
275271 key_id : impl Derivation ,
276272 ) -> Result < monero:: PrivateKey , crypto:: Error > {
277- let path = self . get_derivation_path ( Blockchain :: Monero , key_id ) ?;
273+ let path = key_id . derivation_path ( ) ?;
278274 self . monero_derivations
279275 . get ( & path)
280276 // Option<Result<PrivateKey, _>>
@@ -283,7 +279,7 @@ impl KeyManager {
283279 // None => || { ... } => Result<PrivateKey, crypto::Error>
284280 . unwrap_or_else ( || {
285281 let key_seed = self
286- . monero_master_key
282+ . monero_account_key
287283 . derive_priv ( & path)
288284 . expect ( "Path does not contain non-hardened derivation" )
289285 . secret_key ;
@@ -308,11 +304,17 @@ impl KeyManager {
308304 /// Create a new key manager with the provided master seed, returns an error if the swap index is
309305 /// not within `[0, 2^31 - 1]`.
310306 pub fn new ( seed : [ u8 ; 32 ] , swap_index : u32 ) -> Result < Self , crypto:: Error > {
307+ let swap_index = ChildNumber :: from_hardened_idx ( swap_index) . map_err ( crypto:: Error :: new) ?;
308+ let secp = Secp256k1 :: new ( ) ;
311309 Ok ( Self {
312- master_seed : seed,
313- swap_index : ChildNumber :: from_hardened_idx ( swap_index) . map_err ( crypto:: Error :: new) ?,
314- bitcoin_master_key : Secp256k1ExtSecretKey :: new_master ( seed. as_ref ( ) ) ,
315- monero_master_key : Ed25519ExtSecretKey :: new_master ( seed. as_ref ( ) ) ,
310+ swap_index,
311+ bitcoin_account_key : Secp256k1ExtSecretKey :: new_master ( seed. as_ref ( ) ) . derive_priv (
312+ & secp,
313+ & Self :: get_account_derivation_path ( Blockchain :: Bitcoin , swap_index) ?,
314+ ) ?,
315+ monero_account_key : Ed25519ExtSecretKey :: new_master ( seed. as_ref ( ) ) . derive_priv (
316+ & Self :: get_account_derivation_path ( Blockchain :: Monero , swap_index) ?,
317+ ) ?,
316318 bitcoin_derivations : HashMap :: new ( ) ,
317319 monero_derivations : HashMap :: new ( ) ,
318320 } )
@@ -565,3 +567,45 @@ fn test_keymanager_consensus_encoding() {
565567 key_manager. consensus_encode ( & mut encoder) . unwrap ( ) ;
566568 KeyManager :: consensus_decode ( & mut std:: io:: Cursor :: new ( encoder) ) . unwrap ( ) ;
567569}
570+
571+ #[ test]
572+ fn test_keymanager_restore_index ( ) {
573+ let key_manager = KeyManager :: new ( [ 0 ; 32 ] , 42 ) . unwrap ( ) ;
574+ let mut encoder = Vec :: new ( ) ;
575+ key_manager. consensus_encode ( & mut encoder) . unwrap ( ) ;
576+ let restore = KeyManager :: consensus_decode ( & mut std:: io:: Cursor :: new ( encoder) ) . unwrap ( ) ;
577+ assert_eq ! (
578+ restore. swap_index,
579+ ChildNumber :: from_hardened_idx( 42 ) . unwrap( )
580+ ) ;
581+ }
582+
583+ #[ test]
584+ fn test_keymanager_restore_bitcoin_key ( ) {
585+ let mut key_manager = KeyManager :: new ( [ 0 ; 32 ] , 1 ) . unwrap ( ) ;
586+ let orig_key = key_manager
587+ . get_or_derive_bitcoin_key ( ArbitratingKeyId :: Lock )
588+ . unwrap ( ) ;
589+ let mut encoder = Vec :: new ( ) ;
590+ key_manager. consensus_encode ( & mut encoder) . unwrap ( ) ;
591+ let mut restore = KeyManager :: consensus_decode ( & mut std:: io:: Cursor :: new ( encoder) ) . unwrap ( ) ;
592+ let restored_key = restore
593+ . get_or_derive_bitcoin_key ( ArbitratingKeyId :: Lock )
594+ . unwrap ( ) ;
595+ assert_eq ! ( orig_key, restored_key) ;
596+ }
597+
598+ #[ test]
599+ fn test_keymanager_restore_monero_key ( ) {
600+ let mut key_manager = KeyManager :: new ( [ 0 ; 32 ] , 1 ) . unwrap ( ) ;
601+ let orig_key = key_manager
602+ . get_or_derive_monero_key ( AccordantKeyId :: Spend )
603+ . unwrap ( ) ;
604+ let mut encoder = Vec :: new ( ) ;
605+ key_manager. consensus_encode ( & mut encoder) . unwrap ( ) ;
606+ let mut restore = KeyManager :: consensus_decode ( & mut std:: io:: Cursor :: new ( encoder) ) . unwrap ( ) ;
607+ let restored_key = restore
608+ . get_or_derive_monero_key ( AccordantKeyId :: Spend )
609+ . unwrap ( ) ;
610+ assert_eq ! ( orig_key, restored_key) ;
611+ }
0 commit comments