Merge bitcoindevkit/bdk-ffi#247: Add from_string() methods to DescriptorPrivateKey and DescriptorPublicKey
427816fd9a40223473eb7b7f9f1ba7fe5ea3b277 Add from_string() methods to DescriptorPrivateKey and DescriptorPublicKey (thunderbiscuit) 29614b5b7884c2571cf0085413406f9452fc81d1 Add from_string() methods to DescriptorPrivateKey and DescriptorPublicKey (thunderbiscuit) Pull request description: This PR adds the `from_string()` method to the `DescriptorSecretKey` and `DescriptorPublicKey` structs. ### Description Fixes #246. ### Notes to the reviewers The error thrown is coming from rust-miniscript, so I'm not sure yet how to handle that. ### Changelog notice ```txt APIs Added: - from_string() constructors now available on DescriptorSecretKey and DescriptorPublicKey [#247] [#247](https://github.com/bitcoindevkit/bdk-ffi/pull/247) ``` ### Checklists #### All Submissions: * [x] I've signed all my commits * [x] I followed the [contribution guidelines](https://github.com/bitcoindevkit/bdk/blob/master/CONTRIBUTING.md) * [x] I ran `cargo fmt` and `cargo clippy` before committing #### New Features: * [x] I've added tests for the new feature ACKs for top commit: notmandatory: ACK 427816fd9a40223473eb7b7f9f1ba7fe5ea3b277 Tree-SHA512: a961af10549c92e1750669b148bc56c017c3929ae32199c7b71e51dca760b3dcd039ecbd68873a5175f7b02a2f1b0a94ba22018bc48d596c16d8a7d710c60fea
This commit is contained in:
		
						commit
						8c934e9bfc
					
				@ -304,9 +304,13 @@ interface DerivationPath {
 | 
				
			|||||||
interface DescriptorSecretKey {
 | 
					interface DescriptorSecretKey {
 | 
				
			||||||
  constructor(Network network, Mnemonic mnemonic, string? password);
 | 
					  constructor(Network network, Mnemonic mnemonic, string? password);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [Name=from_string, Throws=BdkError]
 | 
				
			||||||
 | 
					  constructor(string secret_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [Throws=BdkError]
 | 
					  [Throws=BdkError]
 | 
				
			||||||
  DescriptorSecretKey derive(DerivationPath path);
 | 
					  DescriptorSecretKey derive(DerivationPath path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [Throws=BdkError]
 | 
				
			||||||
  DescriptorSecretKey extend(DerivationPath path);
 | 
					  DescriptorSecretKey extend(DerivationPath path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  DescriptorPublicKey as_public();
 | 
					  DescriptorPublicKey as_public();
 | 
				
			||||||
@ -317,9 +321,13 @@ interface DescriptorSecretKey {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface DescriptorPublicKey {
 | 
					interface DescriptorPublicKey {
 | 
				
			||||||
 | 
					  [Name=from_string, Throws=BdkError]
 | 
				
			||||||
 | 
					  constructor(string public_key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  [Throws=BdkError]
 | 
					  [Throws=BdkError]
 | 
				
			||||||
  DescriptorPublicKey derive(DerivationPath path);
 | 
					  DescriptorPublicKey derive(DerivationPath path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  [Throws=BdkError]
 | 
				
			||||||
  DescriptorPublicKey extend(DerivationPath path);
 | 
					  DescriptorPublicKey extend(DerivationPath path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  string as_string();
 | 
					  string as_string();
 | 
				
			||||||
 | 
				
			|||||||
@ -924,6 +924,7 @@ impl DerivationPath {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
struct DescriptorSecretKey {
 | 
					struct DescriptorSecretKey {
 | 
				
			||||||
    descriptor_secret_key_mutex: Mutex<BdkDescriptorSecretKey>,
 | 
					    descriptor_secret_key_mutex: Mutex<BdkDescriptorSecretKey>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -943,6 +944,14 @@ impl DescriptorSecretKey {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn from_string(private_key: String) -> Result<Self, BdkError> {
 | 
				
			||||||
 | 
					        let descriptor_secret_key = BdkDescriptorSecretKey::from_str(private_key.as_str())
 | 
				
			||||||
 | 
					            .map_err(|e| BdkError::Generic(e.to_string()))?;
 | 
				
			||||||
 | 
					        Ok(Self {
 | 
				
			||||||
 | 
					            descriptor_secret_key_mutex: Mutex::new(descriptor_secret_key),
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
 | 
					    fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
 | 
				
			||||||
        let secp = Secp256k1::new();
 | 
					        let secp = Secp256k1::new();
 | 
				
			||||||
        let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
 | 
					        let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
 | 
				
			||||||
@ -964,13 +973,13 @@ impl DescriptorSecretKey {
 | 
				
			|||||||
                    descriptor_secret_key_mutex: Mutex::new(derived_descriptor_secret_key),
 | 
					                    descriptor_secret_key_mutex: Mutex::new(derived_descriptor_secret_key),
 | 
				
			||||||
                }))
 | 
					                }))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            BdkDescriptorSecretKey::Single(_) => {
 | 
					            BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
 | 
				
			||||||
                unreachable!()
 | 
					                "Cannot derive from a single key".to_string(),
 | 
				
			||||||
            }
 | 
					            )),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn extend(&self, path: Arc<DerivationPath>) -> Arc<Self> {
 | 
					    fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
 | 
				
			||||||
        let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
 | 
					        let descriptor_secret_key = self.descriptor_secret_key_mutex.lock().unwrap();
 | 
				
			||||||
        let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
 | 
					        let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
 | 
				
			||||||
        match descriptor_secret_key.deref() {
 | 
					        match descriptor_secret_key.deref() {
 | 
				
			||||||
@ -982,13 +991,13 @@ impl DescriptorSecretKey {
 | 
				
			|||||||
                    derivation_path: extended_path,
 | 
					                    derivation_path: extended_path,
 | 
				
			||||||
                    wildcard: descriptor_x_key.wildcard,
 | 
					                    wildcard: descriptor_x_key.wildcard,
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                Arc::new(Self {
 | 
					                Ok(Arc::new(Self {
 | 
				
			||||||
                    descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key),
 | 
					                    descriptor_secret_key_mutex: Mutex::new(extended_descriptor_secret_key),
 | 
				
			||||||
                })
 | 
					                }))
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            BdkDescriptorSecretKey::Single(_) => {
 | 
					 | 
				
			||||||
                unreachable!()
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            BdkDescriptorSecretKey::Single(_) => Err(BdkError::Generic(
 | 
				
			||||||
 | 
					                "Cannot extend from a single key".to_string(),
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1025,11 +1034,20 @@ impl DescriptorSecretKey {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
struct DescriptorPublicKey {
 | 
					struct DescriptorPublicKey {
 | 
				
			||||||
    descriptor_public_key_mutex: Mutex<BdkDescriptorPublicKey>,
 | 
					    descriptor_public_key_mutex: Mutex<BdkDescriptorPublicKey>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl DescriptorPublicKey {
 | 
					impl DescriptorPublicKey {
 | 
				
			||||||
 | 
					    fn from_string(public_key: String) -> Result<Self, BdkError> {
 | 
				
			||||||
 | 
					        let descriptor_public_key = BdkDescriptorPublicKey::from_str(public_key.as_str())
 | 
				
			||||||
 | 
					            .map_err(|e| BdkError::Generic(e.to_string()))?;
 | 
				
			||||||
 | 
					        Ok(Self {
 | 
				
			||||||
 | 
					            descriptor_public_key_mutex: Mutex::new(descriptor_public_key),
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
 | 
					    fn derive(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
 | 
				
			||||||
        let secp = Secp256k1::new();
 | 
					        let secp = Secp256k1::new();
 | 
				
			||||||
        let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
 | 
					        let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
 | 
				
			||||||
@ -1052,13 +1070,13 @@ impl DescriptorPublicKey {
 | 
				
			|||||||
                    descriptor_public_key_mutex: Mutex::new(derived_descriptor_public_key),
 | 
					                    descriptor_public_key_mutex: Mutex::new(derived_descriptor_public_key),
 | 
				
			||||||
                }))
 | 
					                }))
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            BdkDescriptorPublicKey::Single(_) => {
 | 
					            BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
 | 
				
			||||||
                unreachable!()
 | 
					                "Cannot derive from a single key".to_string(),
 | 
				
			||||||
            }
 | 
					            )),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn extend(&self, path: Arc<DerivationPath>) -> Arc<Self> {
 | 
					    fn extend(&self, path: Arc<DerivationPath>) -> Result<Arc<Self>, BdkError> {
 | 
				
			||||||
        let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
 | 
					        let descriptor_public_key = self.descriptor_public_key_mutex.lock().unwrap();
 | 
				
			||||||
        let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
 | 
					        let path = path.derivation_path_mutex.lock().unwrap().deref().clone();
 | 
				
			||||||
        match descriptor_public_key.deref() {
 | 
					        match descriptor_public_key.deref() {
 | 
				
			||||||
@ -1070,13 +1088,13 @@ impl DescriptorPublicKey {
 | 
				
			|||||||
                    derivation_path: extended_path,
 | 
					                    derivation_path: extended_path,
 | 
				
			||||||
                    wildcard: descriptor_x_key.wildcard,
 | 
					                    wildcard: descriptor_x_key.wildcard,
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
                Arc::new(Self {
 | 
					                Ok(Arc::new(Self {
 | 
				
			||||||
                    descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key),
 | 
					                    descriptor_public_key_mutex: Mutex::new(extended_descriptor_public_key),
 | 
				
			||||||
                })
 | 
					                }))
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            BdkDescriptorPublicKey::Single(_) => {
 | 
					 | 
				
			||||||
                unreachable!()
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            BdkDescriptorPublicKey::Single(_) => Err(BdkError::Generic(
 | 
				
			||||||
 | 
					                "Cannot extend from a single key".to_string(),
 | 
				
			||||||
 | 
					            )),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1176,7 +1194,10 @@ mod test {
 | 
				
			|||||||
        key.derive(path)
 | 
					        key.derive(path)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn extend_dsk(key: &DescriptorSecretKey, path: &str) -> Arc<DescriptorSecretKey> {
 | 
					    fn extend_dsk(
 | 
				
			||||||
 | 
					        key: &DescriptorSecretKey,
 | 
				
			||||||
 | 
					        path: &str,
 | 
				
			||||||
 | 
					    ) -> Result<Arc<DescriptorSecretKey>, BdkError> {
 | 
				
			||||||
        let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
 | 
					        let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
 | 
				
			||||||
        key.extend(path)
 | 
					        key.extend(path)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1189,7 +1210,10 @@ mod test {
 | 
				
			|||||||
        key.derive(path)
 | 
					        key.derive(path)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn extend_dpk(key: &DescriptorPublicKey, path: &str) -> Arc<DescriptorPublicKey> {
 | 
					    fn extend_dpk(
 | 
				
			||||||
 | 
					        key: &DescriptorPublicKey,
 | 
				
			||||||
 | 
					        path: &str,
 | 
				
			||||||
 | 
					    ) -> Result<Arc<DescriptorPublicKey>, BdkError> {
 | 
				
			||||||
        let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
 | 
					        let path = Arc::new(DerivationPath::new(path.to_string()).unwrap());
 | 
				
			||||||
        key.extend(path)
 | 
					        key.extend(path)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1226,12 +1250,34 @@ mod test {
 | 
				
			|||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
    fn test_extend_descriptor_keys() {
 | 
					    fn test_extend_descriptor_keys() {
 | 
				
			||||||
        let master_dsk = get_descriptor_secret_key();
 | 
					        let master_dsk = get_descriptor_secret_key();
 | 
				
			||||||
        let extended_dsk: &DescriptorSecretKey = &extend_dsk(&master_dsk, "m/0");
 | 
					        let extended_dsk: &DescriptorSecretKey = &extend_dsk(&master_dsk, "m/0").unwrap();
 | 
				
			||||||
        assert_eq!(extended_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*");
 | 
					        assert_eq!(extended_dsk.as_string(), "tprv8ZgxMBicQKsPdWuqM1t1CDRvQtQuBPyfL6GbhQwtxDKgUAVPbxmj71pRA8raTqLrec5LyTs5TqCxdABcZr77bt2KyWA5bizJHnC4g4ysm4h/0/*");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
 | 
					        let master_dpk: &DescriptorPublicKey = &master_dsk.as_public();
 | 
				
			||||||
        let extended_dpk: &DescriptorPublicKey = &extend_dpk(master_dpk, "m/0");
 | 
					        let extended_dpk: &DescriptorPublicKey = &extend_dpk(master_dpk, "m/0").unwrap();
 | 
				
			||||||
        assert_eq!(extended_dpk.as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/0/*");
 | 
					        assert_eq!(extended_dpk.as_string(), "tpubD6NzVbkrYhZ4WywdEfYbbd62yuvqLjAZuPsNyvzCNV85JekAEMbKHWSHLF9h3j45SxewXDcLv328B1SEZrxg4iwGfmdt1pDFjZiTkGiFqGa/0/*");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let wif = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch";
 | 
				
			||||||
 | 
					        let extended_key = DescriptorSecretKey::from_string(wif.to_string()).unwrap();
 | 
				
			||||||
 | 
					        let result = extended_key.derive(Arc::new(DerivationPath::new("m/0".to_string()).unwrap()));
 | 
				
			||||||
 | 
					        dbg!(&result);
 | 
				
			||||||
 | 
					        assert!(result.is_err());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[test]
 | 
				
			||||||
 | 
					    fn test_from_str_descriptor_secret_key() {
 | 
				
			||||||
 | 
					        let key1 = "L2wTu6hQrnDMiFNWA5na6jB12ErGQqtXwqpSL7aWquJaZG8Ai3ch";
 | 
				
			||||||
 | 
					        let key2 = "tprv8ZgxMBicQKsPcwcD4gSnMti126ZiETsuX7qwrtMypr6FBwAP65puFn4v6c3jrN9VwtMRMph6nyT63NrfUL4C3nBzPcduzVSuHD7zbX2JKVc/1/1/1/*";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let private_descriptor_key1 = DescriptorSecretKey::from_string(key1.to_string()).unwrap();
 | 
				
			||||||
 | 
					        let private_descriptor_key2 = DescriptorSecretKey::from_string(key2.to_string()).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dbg!(private_descriptor_key1);
 | 
				
			||||||
 | 
					        dbg!(private_descriptor_key2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Should error out because you can't produce a DescriptorSecretKey from an xpub
 | 
				
			||||||
 | 
					        let key0 = "tpubDBrgjcxBxnXyL575sHdkpKohWu5qHKoQ7TJXKNrYznh5fVEGBv89hA8ENW7A8MFVpFUSvgLqc4Nj1WZcpePX6rrxviVtPowvMuGF5rdT2Vi";
 | 
				
			||||||
 | 
					        assert!(DescriptorSecretKey::from_string(key0.to_string()).is_err());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[test]
 | 
					    #[test]
 | 
				
			||||||
@ -1242,7 +1288,7 @@ mod test {
 | 
				
			|||||||
        assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
 | 
					        assert_eq!(derived_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/*");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // extend derived_dsk with path "m/0"
 | 
					        // extend derived_dsk with path "m/0"
 | 
				
			||||||
        let extended_dsk: &DescriptorSecretKey = &extend_dsk(derived_dsk, "m/0");
 | 
					        let extended_dsk: &DescriptorSecretKey = &extend_dsk(derived_dsk, "m/0").unwrap();
 | 
				
			||||||
        assert_eq!(extended_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/0/*");
 | 
					        assert_eq!(extended_dsk.as_string(), "[d1d04177/0]tprv8d7Y4JLmD25jkKbyDZXcdoPHu1YtMHuH21qeN7mFpjfumtSU7eZimFYUCSa3MYzkEYfSNRBV34GEr2QXwZCMYRZ7M1g6PUtiLhbJhBZEGYJ/0/*");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user