Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions key-wallet/examples/basic_usage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn main() -> core::result::Result<(), Box<dyn std::error::Error>> {
// 8. Address parsing example
println!("\n8. Address parsing...");
let test_address = "XyPvhVmhWKDgvMJLwfFfMwhxpxGgd3TBxq";
match key_wallet::address::Address::from_str(test_address) {
match test_address.parse::<key_wallet::address::Address>() {
Ok(parsed) => {
println!(" Parsed address: {}", parsed);
println!(" Type: {:?}", parsed.address_type);
Expand All @@ -84,7 +84,6 @@ fn demonstrate_address_generation() -> core::result::Result<(), Box<dyn std::err
// This demonstrates bulk address generation
let seed = [0u8; 64];
let wallet = HDWallet::from_seed(&seed, Network::Dash)?;
let account = wallet.bip44_account(0)?;
let path = key_wallet::DerivationPath::from(vec![
key_wallet::ChildNumber::from_hardened_idx(44).unwrap(),
key_wallet::ChildNumber::from_hardened_idx(5).unwrap(),
Expand Down
59 changes: 34 additions & 25 deletions key-wallet/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt;
use core::str::FromStr;

use bitcoin_hashes::{hash160, Hash};
use secp256k1::{PublicKey, Secp256k1};
Expand Down Expand Up @@ -97,7 +98,39 @@ impl Address {
}

/// Parse an address from a string (network is inferred from version byte)
pub fn from_str(s: &str) -> Result<Self> {
pub fn from_string(s: &str) -> Result<Self> {
s.parse()
}

/// Get the script pubkey for this address
pub fn script_pubkey(&self) -> Vec<u8> {
match self.address_type {
AddressType::P2PKH => {
let mut script = Vec::with_capacity(25);
script.push(0x76); // OP_DUP
script.push(0xa9); // OP_HASH160
script.push(0x14); // Push 20 bytes
script.extend_from_slice(&self.hash[..]);
script.push(0x88); // OP_EQUALVERIFY
script.push(0xac); // OP_CHECKSIG
script
}
AddressType::P2SH => {
let mut script = Vec::with_capacity(23);
script.push(0xa9); // OP_HASH160
script.push(0x14); // Push 20 bytes
script.extend_from_slice(&self.hash[..]);
script.push(0x87); // OP_EQUAL
script
}
}
}
}

impl FromStr for Address {
type Err = Error;

fn from_str(s: &str) -> Result<Self> {
let data = base58ck::decode_check(s)
.map_err(|_| Error::InvalidAddress("Invalid base58 encoding".into()))?;

Expand Down Expand Up @@ -132,30 +165,6 @@ impl Address {
hash,
})
}

/// Get the script pubkey for this address
pub fn script_pubkey(&self) -> Vec<u8> {
match self.address_type {
AddressType::P2PKH => {
let mut script = Vec::with_capacity(25);
script.push(0x76); // OP_DUP
script.push(0xa9); // OP_HASH160
script.push(0x14); // Push 20 bytes
script.extend_from_slice(&self.hash[..]);
script.push(0x88); // OP_EQUALVERIFY
script.push(0xac); // OP_CHECKSIG
script
}
AddressType::P2SH => {
let mut script = Vec::with_capacity(23);
script.push(0xa9); // OP_HASH160
script.push(0x14); // Push 20 bytes
script.extend_from_slice(&self.hash[..]);
script.push(0x87); // OP_EQUAL
script
}
}
}
}

impl fmt::Display for Address {
Expand Down
12 changes: 8 additions & 4 deletions key-wallet/src/derivation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ impl KeyDerivation for ExtendedPrivKey {
secp: &Secp256k1<C>,
path: &DerivationPath,
) -> Result<ExtendedPrivKey> {
self.derive_priv(secp, path).map_err(Into::into)
self.derive_priv(secp, path).map_err(Error::Bip32)
}

fn derive_pub<C: secp256k1::Signing>(
Expand Down Expand Up @@ -74,7 +74,7 @@ impl HDWallet {

/// Derive a key at the given path
pub fn derive(&self, path: &DerivationPath) -> Result<ExtendedPrivKey> {
self.master_key.derive_priv(&self.secp, path).map_err(Into::into)
self.master_key.derive_priv(&self.secp, path).map_err(Error::Bip32)
}

/// Derive a public key at the given path
Expand Down Expand Up @@ -158,15 +158,19 @@ impl AccountDerivation {
let path = format!("m/0/{}", index)
.parse::<DerivationPath>()
.map_err(|e| Error::InvalidDerivationPath(e.to_string()))?;
self.account_key.derive_pub(&self.secp, &path).map_err(Into::into)
let priv_key = self.account_key.derive_priv(&self.secp, &path)
.map_err(Error::Bip32)?;
Ok(ExtendedPubKey::from_priv(&self.secp, &priv_key))
}

/// Derive an internal (change) address at index
pub fn change_address(&self, index: u32) -> Result<ExtendedPubKey> {
let path = format!("m/1/{}", index)
.parse::<DerivationPath>()
.map_err(|e| Error::InvalidDerivationPath(e.to_string()))?;
self.account_key.derive_pub(&self.secp, &path).map_err(Into::into)
let priv_key = self.account_key.derive_priv(&self.secp, &path)
.map_err(Error::Bip32)?;
Ok(ExtendedPubKey::from_priv(&self.secp, &priv_key))
}
}

Expand Down
2 changes: 1 addition & 1 deletion key-wallet/tests/address_tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Address tests

use std::str::FromStr;
use bitcoin_hashes::{hash160, Hash};
use key_wallet::address::{Address, AddressGenerator, AddressType};
use key_wallet::derivation::HDWallet;
Expand Down Expand Up @@ -98,7 +99,6 @@ fn test_address_generator() {
let wallet = HDWallet::from_seed(&seed, Network::Dash).unwrap();

// Get account public key
let account = wallet.bip44_account(0).unwrap();
let path = key_wallet::DerivationPath::from(vec![
key_wallet::ChildNumber::from_hardened_idx(44).unwrap(),
key_wallet::ChildNumber::from_hardened_idx(5).unwrap(),
Expand Down
2 changes: 1 addition & 1 deletion key-wallet/tests/mnemonic_tests.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Mnemonic tests

use key_wallet::mnemonic::{Language, Mnemonic};
use key_wallet::{ExtendedPrivKey, Network};
use key_wallet::Network;

#[test]
fn test_mnemonic_validation() {
Expand Down
Loading