@@ -149,71 +149,76 @@ public class BIP32Keystore: AbstractKeystore {
149
149
} else {
150
150
newIndex = UInt32 . zero
151
151
}
152
+
152
153
guard let newNode = parentNode. derive ( index: newIndex, derivePrivateKey: true , hardened: false ) else {
153
154
throw AbstractKeystoreError . keyDerivationError
154
155
}
155
156
guard let newAddress = Utilities . publicToAddress ( newNode. publicKey) else {
156
157
throw AbstractKeystoreError . keyDerivationError
157
158
}
158
- let prefixPath = self . rootPrefix
159
- var newPath : String
160
- if newNode. isHardened {
161
- newPath = prefixPath + " / " + String( newNode. index % HDNode. hardenedIndexPrefix) + " ' "
162
- } else {
163
- newPath = prefixPath + " / " + String( newNode. index)
164
- }
159
+ let newPath = rootPrefix + " / " + String( newNode. index)
165
160
addressStorage. add ( address: newAddress, for: newPath)
166
161
}
167
162
168
163
public func createNewCustomChildAccount( password: String , path: String ) throws {
169
- guard let decryptedRootNode = try getPrefixNodeData ( password) else {
164
+ guard let decryptedRootNode = try getPrefixNodeData ( password) ,
165
+ let keystoreParams else {
170
166
throw AbstractKeystoreError . encryptionError ( " Failed to decrypt a keystore " )
171
167
}
172
168
guard let rootNode = HDNode ( decryptedRootNode) else {
173
169
throw AbstractKeystoreError . encryptionError ( " Failed to deserialize a root node " )
174
170
}
175
- let prefixPath = self . rootPrefix
176
- var pathAppendix : String ?
171
+
172
+ let prefixPath = rootPrefix
173
+ var pathAppendix = path
174
+
177
175
if path. hasPrefix ( prefixPath) {
178
- let upperIndex = ( path. range ( of: prefixPath) ? . upperBound) !
179
- if upperIndex < path. endIndex {
180
- pathAppendix = String ( path [ path. index ( after: upperIndex) ] )
176
+ if let upperIndex = ( path. range ( of: prefixPath) ? . upperBound) , upperIndex < path. endIndex {
177
+ pathAppendix = String ( path [ path. index ( after: upperIndex) ..< path. endIndex] )
181
178
} else {
182
179
throw AbstractKeystoreError . encryptionError ( " out of bounds " )
183
180
}
184
-
185
- guard pathAppendix != nil else {
186
- throw AbstractKeystoreError . encryptionError ( " Derivation depth mismatch " )
187
- }
188
- if pathAppendix!. hasPrefix ( " / " ) {
189
- pathAppendix = pathAppendix? . trimmingCharacters ( in: CharacterSet . init ( charactersIn: " / " ) )
190
- }
191
- } else {
192
- if path. hasPrefix ( " / " ) {
193
- pathAppendix = path. trimmingCharacters ( in: CharacterSet . init ( charactersIn: " / " ) )
194
- }
195
181
}
196
- guard pathAppendix != nil else {
197
- throw AbstractKeystoreError . encryptionError ( " Derivation depth mismatch " )
182
+ if pathAppendix. hasPrefix ( " / " ) {
183
+ pathAppendix = pathAppendix . trimmingCharacters ( in : . init ( charactersIn : " / " ) )
198
184
}
199
185
guard rootNode. depth == prefixPath. components ( separatedBy: " / " ) . count - 1 else {
200
186
throw AbstractKeystoreError . encryptionError ( " Derivation depth mismatch " )
201
187
}
202
- guard let newNode = rootNode. derive ( path: pathAppendix! , derivePrivateKey: true ) else {
188
+ guard let newNode = rootNode. derive ( path: pathAppendix, derivePrivateKey: true ) else {
203
189
throw AbstractKeystoreError . keyDerivationError
204
190
}
205
191
guard let newAddress = Utilities . publicToAddress ( newNode. publicKey) else {
206
192
throw AbstractKeystoreError . keyDerivationError
207
193
}
208
- var newPath : String
209
- if newNode. isHardened {
210
- newPath = prefixPath + " / " + pathAppendix!. trimmingCharacters ( in: CharacterSet . init ( charactersIn: " ' " ) ) + " ' "
211
- } else {
212
- newPath = prefixPath + " / " + pathAppendix!
213
- }
194
+
195
+ let newPath = prefixPath + " / " + pathAppendix
196
+
214
197
addressStorage. add ( address: newAddress, for: newPath)
215
- guard let serializedRootNode = rootNode. serialize ( serializePublic: false ) else { throw AbstractKeystoreError . keyDerivationError}
216
- try encryptDataToStorage ( password, data: serializedRootNode, aesMode: self . keystoreParams!. crypto. cipher)
198
+ guard let serializedRootNode = rootNode. serialize ( serializePublic: false ) else {
199
+ throw AbstractKeystoreError . keyDerivationError
200
+ }
201
+ try encryptDataToStorage ( password, data: serializedRootNode, aesMode: keystoreParams. crypto. cipher)
202
+ }
203
+
204
+ /// Fast generation addresses for current account
205
+ /// used to show which addresses the user can get for indices from `0` to `number-1`
206
+ /// - Parameters:
207
+ /// - password: password of seed storage
208
+ /// - number: number of wallets addresses needed to generate from `0` to `number-1`
209
+ /// - Returns: Array of addresses generated from `0` to number bound
210
+ public func getAddressForAccount( password: String , number: UInt ) throws -> [ EthereumAddress ] {
211
+ guard let decryptedRootNode = try ? getPrefixNodeData ( password) ,
212
+ let rootNode = HDNode ( decryptedRootNode) else {
213
+ throw AbstractKeystoreError . encryptionError ( " Failed to decrypt a keystore " )
214
+ }
215
+ return try [ UInt] ( 0 ..< number) . compactMap { number in
216
+ guard rootNode. depth == rootPrefix. components ( separatedBy: " / " ) . count - 1 ,
217
+ let newNode = rootNode. derive ( path: " \( number) " , derivePrivateKey: true ) else {
218
+ throw AbstractKeystoreError . keyDerivationError
219
+ }
220
+ return Utilities . publicToAddress ( newNode. publicKey)
221
+ }
217
222
}
218
223
219
224
fileprivate func encryptDataToStorage( _ password: String , data: Data , dkLen: Int = 32 , N: Int = 4096 , R: Int = 6 , P: Int = 1 , aesMode: String = " aes-128-cbc " ) throws {
0 commit comments