1
- use secp256k1:: PublicKey ;
2
1
use base58:: { FromBase58 , ToBase58 } ;
3
- use sha2:: { Digest , Sha256 } ;
4
2
use ripemd:: Ripemd160 ;
3
+ use secp256k1:: PublicKey ;
4
+ use sha2:: { Digest , Sha256 } ;
5
5
6
6
#[ derive( Clone ) ]
7
7
/// Represents an extended public key (xpub) following the BIP32 specification
8
8
/// This structure contains all necessary components to derive child keys and generate Bitcoin addresses
9
9
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)
15
15
}
16
16
17
17
impl Xpub {
@@ -34,7 +34,6 @@ impl Xpub {
34
34
35
35
/// Converts a Base58 encoded xpub string into an Xpub instance.
36
36
pub fn from_base58 ( xpub : & str ) -> Result < Self , String > {
37
-
38
37
// Decode the xpub from Base58
39
38
let decoded = xpub
40
39
. from_base58 ( )
@@ -91,7 +90,7 @@ impl Xpub {
91
90
92
91
// Calculate double SHA256 checksum (first 4 bytes)
93
92
let checksum = & Sha256 :: digest ( Sha256 :: digest ( & data) ) [ ..4 ] ;
94
-
93
+
95
94
// Append checksum to data
96
95
data. extend_from_slice ( checksum) ;
97
96
@@ -116,7 +115,7 @@ impl Xpub {
116
115
// Create address bytes
117
116
// version (1 byte) + pubkey_hash (20 bytes) + checksum (4 bytes)
118
117
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
120
119
data. extend_from_slice ( & pubkey_hash) ;
121
120
122
121
// Add 4-byte chekcsum (first 4 bytes of double SHA256)
@@ -142,10 +141,11 @@ impl Xpub {
142
141
// parent_pubkey (33 bytes) || child_index (4 bytes)
143
142
let mut data = Vec :: with_capacity ( 37 ) ;
144
143
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)
146
145
147
146
// 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" ) ;
149
149
mac. update ( & data) ;
150
150
let result = mac. finalize ( ) . into_bytes ( ) ;
151
151
@@ -155,9 +155,10 @@ impl Xpub {
155
155
// Compute the child public key
156
156
let secp = secp256k1:: Secp256k1 :: new ( ) ;
157
157
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 ) ?;
161
162
162
163
// Create the child Xpub
163
164
Ok ( Self {
@@ -169,7 +170,7 @@ impl Xpub {
169
170
} )
170
171
}
171
172
172
- /// Generates multiple Bitcoin addresses using BIP32 derivation path
173
+ /// Generates multiple Bitcoin addresses using BIP32 derivation path
173
174
pub fn derive_bip32_addresses ( & self , count : u32 ) -> Result < Vec < String > , String > {
174
175
let mut addresses = Vec :: with_capacity ( count as usize ) ;
175
176
let current = self . clone ( ) ;
@@ -193,7 +194,7 @@ impl Xpub {
193
194
/// Follows m/44'/0'/0'/0/i path structure
194
195
pub fn derive_bip44_addresses ( & self , count : u32 ) -> Result < Vec < String > , String > {
195
196
let mut addresses = Vec :: with_capacity ( count as usize ) ;
196
-
197
+
197
198
//BIP44 path: m/44'/0'/0'/0/i
198
199
let account = match self . derive_non_hardened ( 0 ) {
199
200
Ok ( acc) => acc,
@@ -222,4 +223,4 @@ impl Xpub {
222
223
223
224
u32:: from_be_bytes ( hash160[ 0 ..4 ] . try_into ( ) . unwrap ( ) )
224
225
}
225
- }
226
+ }
0 commit comments