Skip to content

Commit 4e6564f

Browse files
authored
Merge pull request #3 from yigitraphy/bip-tools-refactor
Format code according to Rust style guidelines using rustfmt, including proper import ordering, consistent indentation, and assertion formatting. Update secp256k1 dependency to latest version . No functional changes, purely improvements for code readability and maintainability.
2 parents dbda48a + 4e33794 commit 4e6564f

File tree

5 files changed

+195
-110
lines changed

5 files changed

+195
-110
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ output-dir = "coverage"
1414
html = true
1515

1616
[dependencies]
17-
secp256k1 = "0.27"
17+
secp256k1 = "0.29"
1818
hmac = "0.12"
1919
sha2 = "0.10"
2020
ripemd = "0.1"

README.md

+18
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,24 @@ cargo run bip44 "xpub6CUGRUo..." 5
106106
- Uses secure cryptographic primitives
107107
- No private key handling - focused on public key operations only
108108

109+
### Error Types
110+
111+
- Invalid xpub format
112+
- Base58 decode errors
113+
- Invalid derivation path
114+
- Checksum validation failures
115+
116+
### Performance
117+
Benchmark results on standard hardware (Intel i5, 8GB RAM):
118+
119+
#### BIP32:
120+
- Single address generation: ~0.035ms (34.907 microseconds)
121+
- Batch of 100 addresses: ~3.57ms (3.5683 milliseconds)
122+
123+
#### BIP44:
124+
- Single address generation: ~0.069ms (68.628 microseconds)
125+
- Batch of 100 addresses: ~3.59ms (3.5930 milliseconds)
126+
109127
## Project Structure
110128

111129
```

src/lib.rs

+19-18
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
use secp256k1::PublicKey;
21
use base58::{FromBase58, ToBase58};
3-
use sha2::{Digest, Sha256};
42
use ripemd::Ripemd160;
3+
use secp256k1::PublicKey;
4+
use sha2::{Digest, Sha256};
55

66
#[derive(Clone)]
77
/// Represents an extended public key (xpub) following the BIP32 specification
88
/// This structure contains all necessary components to derive child keys and generate Bitcoin addresses
99
pub struct Xpub {
10-
pub depth: u8, // Depth in the HD tree
11-
pub parent_fingerprint: u32, // Fingerprint of the parent key
12-
pub child_number: u32, // Index of this key
13-
pub chain_code: [u8; 32], // Chain code (32 bytes)
14-
pub public_key: PublicKey, // Compressed public key (33 bytes)
10+
pub depth: u8, // Depth in the HD tree
11+
pub parent_fingerprint: u32, // Fingerprint of the parent key
12+
pub child_number: u32, // Index of this key
13+
pub chain_code: [u8; 32], // Chain code (32 bytes)
14+
pub public_key: PublicKey, // Compressed public key (33 bytes)
1515
}
1616

1717
impl Xpub {
@@ -34,7 +34,6 @@ impl Xpub {
3434

3535
/// Converts a Base58 encoded xpub string into an Xpub instance.
3636
pub fn from_base58(xpub: &str) -> Result<Self, String> {
37-
3837
// Decode the xpub from Base58
3938
let decoded = xpub
4039
.from_base58()
@@ -91,7 +90,7 @@ impl Xpub {
9190

9291
// Calculate double SHA256 checksum (first 4 bytes)
9392
let checksum = &Sha256::digest(Sha256::digest(&data))[..4];
94-
93+
9594
// Append checksum to data
9695
data.extend_from_slice(checksum);
9796

@@ -116,7 +115,7 @@ impl Xpub {
116115
// Create address bytes
117116
// version (1 byte) + pubkey_hash (20 bytes) + checksum (4 bytes)
118117
let mut data = Vec::with_capacity(25);
119-
data.push(0x00); // Version byte for mainnet addresses
118+
data.push(0x00); // Version byte for mainnet addresses
120119
data.extend_from_slice(&pubkey_hash);
121120

122121
// Add 4-byte chekcsum (first 4 bytes of double SHA256)
@@ -142,10 +141,11 @@ impl Xpub {
142141
// parent_pubkey (33 bytes) || child_index (4 bytes)
143142
let mut data = Vec::with_capacity(37);
144143
data.extend_from_slice(&self.public_key.serialize()); // Parent public key (33 bytes)
145-
data.extend_from_slice(&index.to_be_bytes()); // Child index (4 bytes)
144+
data.extend_from_slice(&index.to_be_bytes()); // Child index (4 bytes)
146145

147146
// Generate child key material using HMAC-SHA512
148-
let mut mac = HmacSha512::new_from_slice(&self.chain_code).expect("HMAC can take a key of any size");
147+
let mut mac =
148+
HmacSha512::new_from_slice(&self.chain_code).expect("HMAC can take a key of any size");
149149
mac.update(&data);
150150
let result = mac.finalize().into_bytes();
151151

@@ -155,9 +155,10 @@ impl Xpub {
155155
// Compute the child public key
156156
let secp = secp256k1::Secp256k1::new();
157157
let tweak = secp256k1::SecretKey::from_slice(i_l)?;
158-
let child_pubkey = self.public_key
159-
.add_exp_tweak(&secp, &tweak.into())
160-
.map_err(|_| secp256k1::Error::InvalidTweak)?;
158+
let child_pubkey = self
159+
.public_key
160+
.add_exp_tweak(&secp, &tweak.into())
161+
.map_err(|_| secp256k1::Error::InvalidTweak)?;
161162

162163
// Create the child Xpub
163164
Ok(Self {
@@ -169,7 +170,7 @@ impl Xpub {
169170
})
170171
}
171172

172-
/// Generates multiple Bitcoin addresses using BIP32 derivation path
173+
/// Generates multiple Bitcoin addresses using BIP32 derivation path
173174
pub fn derive_bip32_addresses(&self, count: u32) -> Result<Vec<String>, String> {
174175
let mut addresses = Vec::with_capacity(count as usize);
175176
let current = self.clone();
@@ -193,7 +194,7 @@ impl Xpub {
193194
/// Follows m/44'/0'/0'/0/i path structure
194195
pub fn derive_bip44_addresses(&self, count: u32) -> Result<Vec<String>, String> {
195196
let mut addresses = Vec::with_capacity(count as usize);
196-
197+
197198
//BIP44 path: m/44'/0'/0'/0/i
198199
let account = match self.derive_non_hardened(0) {
199200
Ok(acc) => acc,
@@ -222,4 +223,4 @@ impl Xpub {
222223

223224
u32::from_be_bytes(hash160[0..4].try_into().unwrap())
224225
}
225-
}
226+
}

0 commit comments

Comments
 (0)