1 package waddrmgr
2 3 import (
4 "fmt"
5 "github.com/p9c/p9/pkg/btcaddr"
6 "github.com/p9c/p9/pkg/chaincfg"
7 "sync"
8 9 ec "github.com/p9c/p9/pkg/ecc"
10 "github.com/p9c/p9/pkg/util"
11 "github.com/p9c/p9/pkg/util/hdkeychain"
12 "github.com/p9c/p9/pkg/util/zero"
13 "github.com/p9c/p9/pkg/walletdb"
14 )
15 16 // DerivationPath represents a derivation path from a particular key manager's
17 // scope.
18 //
19 // Each ScopedKeyManager starts key derivation from the end of their cointype
20 // hardened key: m/purpose'/cointype'. The fields in this struct allow further
21 // derivation to the next three child levels after the coin type key.
22 //
23 // This restriction is in the spriti of BIP0044 type derivation. We maintain a
24 // degree of coherency with the standard, but allow arbitrary derivations beyond
25 // the cointype key.
26 //
27 // The key derived using this path will be exactly:
28 // m/purpose'/cointype'/account/branch/index, where purpose' and cointype' are
29 // bound by the scope of a particular manager.
30 type DerivationPath struct {
31 // Account is the account, or the first immediate child from the scoped
32 // manager's hardened coin type key.
33 Account uint32
34 // Branch is the branch to be derived from the account index above. For
35 // BIP0044-like derivation, this is either 0 (external) or 1 (internal).
36 // However, we allow this value to vary arbitrarily within its size range.
37 Branch uint32
38 // Index is the final child in the derivation path. This denotes the key index
39 // within as a child of the account and branch.
40 Index uint32
41 }
42 43 // KeyScope represents a restricted key scope from the primary root key within
44 // the HD chain. From the root manager (m/) we can create a nearly arbitrary
45 // number of ScopedKeyManagers of key derivation path: m/purpose'/cointype'.
46 // These scoped managers can then me managed indecently, as they house the
47 // encrypted cointype key and can derive any child keys from there on.
48 type KeyScope struct {
49 // Purpose is the purpose of this key scope. This is the first child of the
50 // master HD key.
51 Purpose uint32
52 // Coin is a value that represents the particular coin which is the child of the
53 // purpose key. With this key, any accounts, or other children can be derived at
54 // all.
55 Coin uint32
56 }
57 58 // ScopedIndex is a tuple of KeyScope and child Index. This is used to compactly
59 // identify a particular child key, when the account and branch can be inferred
60 // from context.
61 type ScopedIndex struct {
62 // Scope is the BIP44 account' used to derive the child key.
63 Scope KeyScope
64 // Index is the BIP44 address_index used to derive the child key.
65 Index uint32
66 }
67 68 // String returns a human readable version describing the keypath encapsulated
69 // by the target key scope.
70 func (k *KeyScope) String() string {
71 return fmt.Sprintf("m/%v'/%v'", k.Purpose, k.Coin)
72 }
73 74 // ScopeAddrSchema is the address schema of a particular KeyScope. This will be
75 // persisted within the database, and will be consulted when deriving any keys
76 // for a particular scope to know how to encode the public keys as addresses.
77 type ScopeAddrSchema struct {
78 // ExternalAddrType is the address type for all keys within branch 0.
79 ExternalAddrType AddressType
80 // InternalAddrType is the address type for all keys within branch 1 (change addresses).
81 InternalAddrType AddressType
82 }
83 84 // // KeyScopeBIP0049Plus is the key scope of our modified BIP0049 derivation. We
85 // // say this is BIP0049 "plus", as we'll actually use p2wkh change all change
86 // // addresses.
87 // KeyScopeBIP0049Plus = KeyScope{
88 // Purpose: 49,
89 // Coin: 0,
90 // }
91 // // KeyScopeBIP0084 is the key scope for BIP0084 derivation. BIP0084 will be used
92 // // to derive all p2wkh addresses.
93 // KeyScopeBIP0084 = KeyScope{
94 // Purpose: 84,
95 // Coin: 0,
96 // }
97 98 var (
99 // KeyScopeBIP0044 is the key scope for BIP0044 derivation. Legacy wallets will
100 // only be able to use this key scope, and no keys beyond it.
101 KeyScopeBIP0044 = KeyScope{
102 Purpose: 44,
103 Coin: 0,
104 }
105 // DefaultKeyScopes is the set of default key scopes that will be created by the
106 // root manager upon initial creation.
107 DefaultKeyScopes = []KeyScope{
108 // KeyScopeBIP0049Plus,
109 // KeyScopeBIP0084,
110 KeyScopeBIP0044,
111 }
112 // ScopeAddrMap is a map from the default key scopes to the scope address schema
113 // for each scope type. This will be consulted during the initial creation of
114 // the root key manager.
115 ScopeAddrMap = map[KeyScope]ScopeAddrSchema{
116 // KeyScopeBIP0049Plus: {
117 // ExternalAddrType: NestedWitnessPubKey,
118 // InternalAddrType: WitnessPubKey,
119 // },
120 // KeyScopeBIP0084: {
121 // ExternalAddrType: WitnessPubKey,
122 // InternalAddrType: WitnessPubKey,
123 // },
124 KeyScopeBIP0044: {
125 InternalAddrType: PubKeyHash,
126 ExternalAddrType: PubKeyHash,
127 },
128 }
129 )
130 131 // ScopedKeyManager is a sub key manager under the main root key manager. The
132 // root key manager will handle the root HD key (m/), while each sub scoped key
133 // manager will handle the cointype key for a particular key scope
134 // (m/purpose'/cointype'). This abstraction allows higher-level applications
135 // built upon the root key manager to perform their own arbitrary key
136 // derivation, while still being protected under the encryption of the root key
137 // manager.
138 type ScopedKeyManager struct {
139 // scope is the scope of this key manager. We can only generate keys that are
140 // direct children of this scope.
141 scope KeyScope
142 // addrSchema is the address schema for this sub manager. This will be consulted
143 // when encoding addresses from derived keys.
144 addrSchema ScopeAddrSchema
145 // rootManager is a pointer to the root key manager. We'll maintain this as we
146 // need access to the crypto encryption keys before we can derive any new
147 // accounts of child keys of accounts.
148 rootManager *Manager
149 // addrs is a cached map of all the addresses that we currently manager.
150 addrs map[addrKey]ManagedAddress
151 // acctInfo houses information about accounts including what is needed to
152 // generate deterministic chained keys for each created account.
153 acctInfo map[uint32]*accountInfo
154 // deriveOnUnlock is a list of private keys which needs to be derived on the
155 // next unlock. This occurs when a public address is derived while the address
156 // manager is locked since it does not have access to the private extended key
157 // (hence nor the underlying private key) in order to encrypt it.
158 deriveOnUnlock []*unlockDeriveInfo
159 mtx sync.RWMutex
160 }
161 162 // Scope returns the exact KeyScope of this scoped key manager.
163 func (s *ScopedKeyManager) Scope() KeyScope {
164 return s.scope
165 }
166 167 // AddrSchema returns the set address schema for the target ScopedKeyManager.
168 func (s *ScopedKeyManager) AddrSchema() ScopeAddrSchema {
169 return s.addrSchema
170 }
171 172 // zeroSensitivePublicData performs a best try effort to remove and zero all
173 // sensitive public data associated with the address manager such as
174 // hierarchical deterministic extended public keys and the crypto public keys.
175 func (s *ScopedKeyManager) zeroSensitivePublicData() {
176 // Clear all of the account private keys.
177 for _, acctInfo := range s.acctInfo {
178 acctInfo.acctKeyPub.Zero()
179 acctInfo.acctKeyPub = nil
180 }
181 }
182 183 // Close cleanly shuts down the manager. It makes a best try effort to remove
184 // and zero all private key and sensitive public key material associated with
185 // the address manager from memory.
186 func (s *ScopedKeyManager) Close() {
187 s.mtx.Lock()
188 defer s.mtx.Unlock()
189 // Attempt to clear sensitive public key material from memory too.
190 s.zeroSensitivePublicData()
191 // return
192 }
193 194 // keyToManaged returns a new managed address for the provided derived key and
195 // its derivation path which consists of the account, branch, and index.
196 //
197 // The passed derivedKey is zeroed after the new address is created.
198 //
199 // This function MUST be called with the manager lock held for writes.
200 func (s *ScopedKeyManager) keyToManaged(
201 derivedKey *hdkeychain.ExtendedKey,
202 account, branch, index uint32,
203 ) (ManagedAddress, error) {
204 var addrType AddressType
205 if branch == InternalBranch {
206 addrType = s.addrSchema.InternalAddrType
207 } else {
208 addrType = s.addrSchema.ExternalAddrType
209 }
210 derivationPath := DerivationPath{
211 Account: account,
212 Branch: branch,
213 Index: index,
214 }
215 // Create a new managed address based on the public or private key depending on
216 // whether the passed key is private. Also, zero the key after creating the
217 // managed address from it.
218 ma, e := newManagedAddressFromExtKey(
219 s, derivationPath, derivedKey, addrType,
220 )
221 defer derivedKey.Zero()
222 if e != nil {
223 return nil, e
224 }
225 if !derivedKey.IsPrivate() {
226 // Add the managed address to the list of addresses that need their private keys
227 // derived when the address manager is next unlocked.
228 info := unlockDeriveInfo{
229 managedAddr: ma,
230 branch: branch,
231 index: index,
232 }
233 s.deriveOnUnlock = append(s.deriveOnUnlock, &info)
234 }
235 if branch == InternalBranch {
236 ma.internal = true
237 }
238 return ma, nil
239 }
240 241 // deriveKey returns either a public or private derived extended key based on
242 // the private flag for the given an account info, branch, and index.
243 func (s *ScopedKeyManager) deriveKey(
244 acctInfo *accountInfo, branch,
245 index uint32, private bool,
246 ) (addressKey *hdkeychain.ExtendedKey, e error) {
247 // Choose the public or private extended key based on whether or not the private
248 // flag was specified. This, in turn, allows for public or private child
249 // derivation.
250 acctKey := acctInfo.acctKeyPub
251 if private {
252 acctKey = acctInfo.acctKeyPriv
253 }
254 // Derive and return the key.
255 var branchKey *hdkeychain.ExtendedKey
256 if branchKey, e = acctKey.Child(branch); E.Chk(e) {
257 str := fmt.Sprintf("failed to derive extended key branch %d", branch)
258 return nil, managerError(ErrKeyChain, str, e)
259 }
260 if addressKey, e = branchKey.Child(index); E.Chk(e) {
261 branchKey.Zero() // Zero branch key after it's used.
262 str := fmt.Sprintf("failed to derive child extended key -- branch %d, child %d", branch, index)
263 return nil, managerError(ErrKeyChain, str, e)
264 }
265 branchKey.Zero() // Zero branch key after it's used.
266 return
267 }
268 269 // loadAccountInfo attempts to load and cache information about the given
270 // account from the database. This includes what is necessary to derive new keys
271 // for it and track the state of the internal and external branches.
272 //
273 // This function MUST be called with the manager lock held for writes.
274 func (s *ScopedKeyManager) loadAccountInfo(
275 ns walletdb.ReadBucket,
276 account uint32,
277 ) (*accountInfo, error) {
278 // Return the account info from cache if it's available.
279 if acctInfo, ok := s.acctInfo[account]; ok {
280 return acctInfo, nil
281 }
282 // The account is either invalid or just wasn't cached, so attempt to load the
283 // information from the database.
284 var e error
285 var rowInterface interface{}
286 if rowInterface, e = fetchAccountInfo(ns, &s.scope, account); E.Chk(e) {
287 return nil, maybeConvertDbError(e)
288 }
289 // Ensure the account type is a default account.
290 ok := false
291 var row *dbDefaultAccountRow
292 if row, ok = rowInterface.(*dbDefaultAccountRow); !ok {
293 str := fmt.Sprintf("unsupported account type %T", row)
294 return nil, managerError(ErrDatabase, str, nil)
295 }
296 // Use the crypto public key to decrypt the account public extended key.
297 var serializedKeyPub []byte
298 if serializedKeyPub, e = s.rootManager.cryptoKeyPub.Decrypt(row.pubKeyEncrypted); E.Chk(e) {
299 str := fmt.Sprintf("failed to decrypt public key for account %d", account)
300 return nil, managerError(ErrCrypto, str, e)
301 }
302 var acctKeyPub *hdkeychain.ExtendedKey
303 if acctKeyPub, e = hdkeychain.NewKeyFromString(string(serializedKeyPub)); E.Chk(e) {
304 str := fmt.Sprintf("failed to create extended public key for account %d", account)
305 return nil, managerError(ErrKeyChain, str, e)
306 }
307 // Create the new account info with the known information. The rest of the
308 // fields are filled out below.
309 acctInfo := &accountInfo{
310 acctName: row.name,
311 acctKeyEncrypted: row.privKeyEncrypted,
312 acctKeyPub: acctKeyPub,
313 nextExternalIndex: row.nextExternalIndex,
314 nextInternalIndex: row.nextInternalIndex,
315 }
316 if !s.rootManager.isLocked() {
317 // Use the crypto private key to decrypt the account private extended keys.
318 var decrypted []byte
319 if decrypted, e = s.rootManager.cryptoKeyPriv.Decrypt(acctInfo.acctKeyEncrypted); E.Chk(e) {
320 str := fmt.Sprintf("failed to decrypt private key for account %d", account)
321 return nil, managerError(ErrCrypto, str, e)
322 }
323 var acctKeyPriv *hdkeychain.ExtendedKey
324 if acctKeyPriv, e = hdkeychain.NewKeyFromString(string(decrypted)); E.Chk(e) {
325 str := fmt.Sprintf("failed to create extended private key for account %d", account)
326 return nil, managerError(ErrKeyChain, str, e)
327 }
328 acctInfo.acctKeyPriv = acctKeyPriv
329 }
330 // Derive and cache the managed address for the last external address.
331 branch, index := ExternalBranch, row.nextExternalIndex
332 if index > 0 {
333 index--
334 }
335 var lastExtKey *hdkeychain.ExtendedKey
336 if lastExtKey, e = s.deriveKey(acctInfo, branch, index, !s.rootManager.isLocked()); E.Chk(e) {
337 return nil, e
338 }
339 var lastExtAddr ManagedAddress
340 if lastExtAddr, e = s.keyToManaged(lastExtKey, account, branch, index); E.Chk(e) {
341 return nil, e
342 }
343 acctInfo.lastExternalAddr = lastExtAddr
344 // Derive and cache the managed address for the last internal address.
345 if branch, index = InternalBranch, row.nextInternalIndex; index > 0 {
346 index--
347 }
348 var lastIntKey *hdkeychain.ExtendedKey
349 if lastIntKey, e = s.deriveKey(acctInfo, branch, index, !s.rootManager.isLocked()); E.Chk(e) {
350 return nil, e
351 }
352 var lastIntAddr ManagedAddress
353 if lastIntAddr, e = s.keyToManaged(lastIntKey, account, branch, index); E.Chk(e) {
354 return nil, e
355 }
356 acctInfo.lastInternalAddr = lastIntAddr
357 // Add it to the cache and return it when everything is successful.
358 s.acctInfo[account] = acctInfo
359 return acctInfo, nil
360 }
361 362 // AccountProperties returns properties associated with the account, such as the
363 // account number, name, and the number of derived and imported keys.
364 func (s *ScopedKeyManager) AccountProperties(
365 ns walletdb.ReadBucket,
366 account uint32,
367 ) (*AccountProperties, error) {
368 defer s.mtx.RUnlock()
369 s.mtx.RLock()
370 props := &AccountProperties{AccountNumber: account}
371 // Until keys can be imported into any account, special handling is required for
372 // the imported account.
373 //
374 // loadAccountInfo errors when using it on the imported account since the
375 // accountInfo struct is filled with a BIP0044 account's extended keys, and the
376 // imported accounts has none.
377 //
378 // Since only the imported account allows imports currently, the number of
379 // imported keys for any other account is zero, and since the imported account
380 // cannot contain non-imported keys, the external and internal key counts for it
381 // are zero.
382 var e error
383 if account != ImportedAddrAccount {
384 var acctInfo *accountInfo
385 if acctInfo, e = s.loadAccountInfo(ns, account); E.Chk(e) {
386 return nil, e
387 }
388 props.AccountName = acctInfo.acctName
389 props.ExternalKeyCount = acctInfo.nextExternalIndex
390 props.InternalKeyCount = acctInfo.nextInternalIndex
391 } else {
392 props.AccountName = ImportedAddrAccountName // reserved, nonchangable
393 // Could be more efficient if this was tracked by the db.
394 var importedKeyCount uint32
395 count := func(interface{}) (e error) {
396 importedKeyCount++
397 return nil
398 }
399 if e = forEachAccountAddress(ns, &s.scope, ImportedAddrAccount, count); E.Chk(e) {
400 return nil, e
401 }
402 props.ImportedKeyCount = importedKeyCount
403 }
404 return props, nil
405 }
406 407 // DeriveFromKeyPath attempts to derive a maximal child key (under the BIP0044
408 // scheme) from a given key path. If key derivation isn't possible, then an
409 // error will be returned.
410 func (s *ScopedKeyManager) DeriveFromKeyPath(
411 ns walletdb.ReadBucket,
412 kp DerivationPath,
413 ) (ManagedAddress, error) {
414 s.mtx.Lock()
415 defer s.mtx.Unlock()
416 var extKey *hdkeychain.ExtendedKey
417 var e error
418 if extKey, e = s.deriveKeyFromPath(
419 ns, kp.Account, kp.Branch, kp.Index, !s.rootManager.IsLocked(),
420 ); E.Chk(e) {
421 return nil, e
422 }
423 return s.keyToManaged(extKey, kp.Account, kp.Branch, kp.Index)
424 }
425 426 // deriveKeyFromPath returns either a public or private derived extended key
427 // based on the private flag for the given an account, branch, and index.
428 //
429 // This function MUST be called with the manager lock held for writes.
430 func (s *ScopedKeyManager) deriveKeyFromPath(
431 ns walletdb.ReadBucket, account, branch,
432 index uint32, private bool,
433 ) (*hdkeychain.ExtendedKey, error) {
434 // Look up the account key information.
435 var acctInfo *accountInfo
436 var e error
437 if acctInfo, e = s.loadAccountInfo(ns, account); E.Chk(e) {
438 return nil, e
439 }
440 return s.deriveKey(acctInfo, branch, index, private)
441 }
442 443 // chainAddressRowToManaged returns a new managed address based on chained
444 // address data loaded from the database.
445 //
446 // This function MUST be called with the manager lock held for writes.
447 func (s *ScopedKeyManager) chainAddressRowToManaged(
448 ns walletdb.ReadBucket,
449 row *dbChainAddressRow,
450 ) (ManagedAddress, error) {
451 // Since the manger's mutex is assumed to held when invoking this function, we
452 // use the internal isLocked to avoid a deadlock.
453 isLocked := s.rootManager.isLocked()
454 var addressKey *hdkeychain.ExtendedKey
455 var e error
456 if addressKey, e = s.deriveKeyFromPath(ns, row.account, row.branch, row.index, !isLocked); E.Chk(e) {
457 return nil, e
458 }
459 return s.keyToManaged(addressKey, row.account, row.branch, row.index)
460 }
461 462 // importedAddressRowToManaged returns a new managed address based on imported
463 // address data loaded from the database.
464 func (s *ScopedKeyManager) importedAddressRowToManaged(row *dbImportedAddressRow) (ManagedAddress, error) {
465 // Use the crypto public key to decrypt the imported public key.
466 var pubBytes []byte
467 var e error
468 if pubBytes, e = s.rootManager.cryptoKeyPub.Decrypt(row.encryptedPubKey); E.Chk(e) {
469 str := "failed to decrypt public key for imported address"
470 return nil, managerError(ErrCrypto, str, e)
471 }
472 var pubKey *ec.PublicKey
473 if pubKey, e = ec.ParsePubKey(pubBytes, ec.S256()); E.Chk(e) {
474 str := "invalid public key for imported address"
475 return nil, managerError(ErrCrypto, str, e)
476 }
477 // Since this is an imported address, we won't populate the full derivation
478 // path, as we don't have enough information to do so.
479 derivationPath := DerivationPath{
480 Account: row.account,
481 }
482 compressed := len(pubBytes) == ec.PubKeyBytesLenCompressed
483 var ma *managedAddress
484 if ma, e = newManagedAddressWithoutPrivKey(
485 s, derivationPath, pubKey, compressed,
486 s.addrSchema.ExternalAddrType,
487 ); E.Chk(e) {
488 return nil, e
489 }
490 ma.privKeyEncrypted = row.encryptedPrivKey
491 ma.imported = true
492 return ma, nil
493 }
494 495 // scriptAddressRowToManaged returns a new managed address based on script
496 // address data loaded from the database.
497 func (s *ScopedKeyManager) scriptAddressRowToManaged(row *dbScriptAddressRow) (ManagedAddress, error) {
498 // Use the crypto public key to decrypt the imported script hash.
499 var scriptHash []byte
500 var e error
501 if scriptHash, e = s.rootManager.cryptoKeyPub.Decrypt(row.encryptedHash); E.Chk(e) {
502 str := "failed to decrypt imported script hash"
503 return nil, managerError(ErrCrypto, str, e)
504 }
505 return newScriptAddress(s, row.account, scriptHash, row.encryptedScript)
506 }
507 508 // rowInterfaceToManaged returns a new managed address based on the given
509 // address data loaded from the database. It will automatically select the
510 // appropriate type.
511 //
512 // This function MUST be called with the manager lock held for writes.
513 func (s *ScopedKeyManager) rowInterfaceToManaged(
514 ns walletdb.ReadBucket,
515 rowInterface interface{},
516 ) (ManagedAddress, error) {
517 switch row := rowInterface.(type) {
518 case *dbChainAddressRow:
519 return s.chainAddressRowToManaged(ns, row)
520 case *dbImportedAddressRow:
521 return s.importedAddressRowToManaged(row)
522 case *dbScriptAddressRow:
523 return s.scriptAddressRowToManaged(row)
524 }
525 str := fmt.Sprintf("unsupported address type %T", rowInterface)
526 return nil, managerError(ErrDatabase, str, nil)
527 }
528 529 // loadAndCacheAddress attempts to load the passed address from the database and caches the associated managed address.
530 //
531 // This function MUST be called with the manager lock held for writes.
532 func (s *ScopedKeyManager) loadAndCacheAddress(
533 ns walletdb.ReadBucket,
534 address btcaddr.Address,
535 ) (ManagedAddress, error) {
536 // Attempt to load the raw address information from the database.
537 rowInterface, e := fetchAddress(ns, &s.scope, address.ScriptAddress())
538 if e != nil {
539 if merr, ok := e.(*ManagerError); ok {
540 desc := fmt.Sprintf(
541 "failed to fetch address '%s': %v",
542 address.ScriptAddress(), merr.Description,
543 )
544 merr.Description = desc
545 return nil, merr
546 }
547 return nil, maybeConvertDbError(e)
548 }
549 // Create a new managed address for the specific type of address based on type.
550 var managedAddr ManagedAddress
551 if managedAddr, e = s.rowInterfaceToManaged(ns, rowInterface); E.Chk(e) {
552 return nil, e
553 }
554 // Cache and return the new managed address.
555 s.addrs[addrKey(managedAddr.Address().ScriptAddress())] = managedAddr
556 return managedAddr, nil
557 }
558 559 // existsAddress returns whether or not the passed address is known to the
560 // address manager.
561 //
562 // This function MUST be called with the manager lock held for reads.
563 func (s *ScopedKeyManager) existsAddress(ns walletdb.ReadBucket, addressID []byte) bool {
564 // Chk the in-memory map first since it's faster than a db access.
565 if _, ok := s.addrs[addrKey(addressID)]; ok {
566 return true
567 }
568 // Chk the database if not already found above.
569 return existsAddress(ns, &s.scope, addressID)
570 }
571 572 // Address returns a managed address given the passed address if it is known to
573 // the address manager. A managed address differs from the passed address in
574 // that it also potentially contains extra information needed to sign
575 // transactions such as the associated private key for pay-to-pubkey and
576 // pay-to-pubkey-hash addresses and the script associated with
577 // pay-to-script-hash addresses.
578 func (s *ScopedKeyManager) Address(
579 ns walletdb.ReadBucket,
580 addr btcaddr.Address,
581 ) (ma ManagedAddress, e error) {
582 // ScriptAddress will only return a script hash if we're accessing an address
583 // that is either PKH or SH. In the event we're passed a PK address, convert the
584 // PK to PKH address so that we can access it from the addrs map and database.
585 ok := false
586 var pka *btcaddr.PubKey
587 if pka, ok = addr.(*btcaddr.PubKey); ok {
588 addr = pka.PubKeyHash()
589 }
590 // Return the address from cache if it's available.
591 //
592 // NOTE: Not using a defer on the lock here since a write lock is needed if the
593 // lookup fails.
594 s.mtx.RLock()
595 if ma, ok = s.addrs[addrKey(addr.ScriptAddress())]; ok {
596 s.mtx.RUnlock()
597 return ma, nil
598 }
599 s.mtx.RUnlock()
600 s.mtx.Lock()
601 defer s.mtx.Unlock()
602 // Attempt to load the address from the database.
603 return s.loadAndCacheAddress(ns, addr)
604 }
605 606 // AddrAccount returns the account to which the given address belongs.
607 func (s *ScopedKeyManager) AddrAccount(
608 ns walletdb.ReadBucket,
609 address btcaddr.Address,
610 ) (account uint32, e error) {
611 if account, e = fetchAddrAccount(ns, &s.scope, address.ScriptAddress()); T.Chk(e) {
612 return 0, maybeConvertDbError(e)
613 }
614 return account, nil
615 }
616 617 // nextAddresses returns the specified number of next chained address from the
618 // branch indicated by the internal flag.
619 //
620 // This function MUST be called with the manager lock held for writes.
621 func (s *ScopedKeyManager) nextAddresses(
622 ns walletdb.ReadWriteBucket,
623 account uint32, numAddresses uint32, internal bool,
624 ) ([]ManagedAddress, error) {
625 // The next address can only be generated for accounts that have already been
626 // created.
627 var acctInfo *accountInfo
628 var e error
629 if acctInfo, e = s.loadAccountInfo(ns, account); E.Chk(e) {
630 return nil, e
631 }
632 // Choose the account key to used based on whether the address manager is
633 // locked.
634 acctKey := acctInfo.acctKeyPub
635 if !s.rootManager.IsLocked() {
636 acctKey = acctInfo.acctKeyPriv
637 }
638 // Choose the branch key and index depending on whether or not this is an
639 // internal address.
640 branchNum, nextIndex := ExternalBranch, acctInfo.nextExternalIndex
641 if internal {
642 branchNum = InternalBranch
643 nextIndex = acctInfo.nextInternalIndex
644 }
645 addrType := s.addrSchema.ExternalAddrType
646 if internal {
647 addrType = s.addrSchema.InternalAddrType
648 }
649 // Ensure the requested number of addresses doesn't exceed the maximum allowed
650 // for this account.
651 if numAddresses > MaxAddressesPerAccount || nextIndex+numAddresses >
652 MaxAddressesPerAccount {
653 str := fmt.Sprintf(
654 "%d new addresses would exceed the maximum "+
655 "allowed number of addresses per account of %d",
656 numAddresses, MaxAddressesPerAccount,
657 )
658 return nil, managerError(ErrTooManyAddresses, str, nil)
659 }
660 // Derive the appropriate branch key and ensure it is zeroed when done.
661 var branchKey *hdkeychain.ExtendedKey
662 if branchKey, e = acctKey.Child(branchNum); E.Chk(e) {
663 str := fmt.Sprintf(
664 "failed to derive extended key branch %d",
665 branchNum,
666 )
667 return nil, managerError(ErrKeyChain, str, e)
668 }
669 defer branchKey.Zero() // Ensure branch key is zeroed when done.
670 // Create the requested number of addresses and keep track of the index with
671 // each one.
672 addressInfo := make([]*unlockDeriveInfo, 0, numAddresses)
673 for i := uint32(0); i < numAddresses; i++ {
674 // There is an extremely small chance that a particular child is invalid, so use
675 // a loop to derive the next valid child.
676 var nextKey *hdkeychain.ExtendedKey
677 for {
678 // Derive the next child in the external chain branch.
679 var key *hdkeychain.ExtendedKey
680 if key, e = branchKey.Child(nextIndex); E.Chk(e) {
681 // When this particular child is invalid, skip to the next index.
682 if e == hdkeychain.ErrInvalidChild {
683 nextIndex++
684 continue
685 }
686 str := fmt.Sprintf(
687 "failed to generate child %d",
688 nextIndex,
689 )
690 return nil, managerError(ErrKeyChain, str, e)
691 }
692 key.SetNet(s.rootManager.chainParams)
693 nextIndex++
694 nextKey = key
695 break
696 }
697 // Now that we know this key can be used, we'll create the proper derivation
698 // path so this information can be available to callers.
699 derivationPath := DerivationPath{
700 Account: account,
701 Branch: branchNum,
702 Index: nextIndex - 1,
703 }
704 // Create a new managed address based on the public or private key depending on
705 // whether the generated key is private. Also, zero the next key after creating
706 // the managed address from it.
707 var addr *managedAddress
708 if addr, e = newManagedAddressFromExtKey(s, derivationPath, nextKey, addrType); E.Chk(e) {
709 return nil, e
710 }
711 if internal {
712 addr.internal = true
713 }
714 managedAddr := addr
715 nextKey.Zero()
716 info := unlockDeriveInfo{
717 managedAddr: managedAddr,
718 branch: branchNum,
719 index: nextIndex - 1,
720 }
721 addressInfo = append(addressInfo, &info)
722 }
723 // Now that all addresses have been successfully generated, update the database
724 // in a single transaction.
725 for _, info := range addressInfo {
726 ma := info.managedAddr
727 addressID := ma.Address().ScriptAddress()
728 switch a := ma.(type) {
729 case *managedAddress:
730 if e = putChainedAddress(
731 ns, &s.scope, addressID, account, ssFull,
732 info.branch, info.index, adtChain,
733 ); E.Chk(e) {
734 return nil, maybeConvertDbError(e)
735 }
736 case *scriptAddress:
737 var encryptedHash []byte
738 if encryptedHash, e = s.rootManager.cryptoKeyPub.Encrypt(a.AddrHash()); E.Chk(e) {
739 str := fmt.Sprintf("failed to encrypt script hash %x", a.AddrHash())
740 return nil, managerError(ErrCrypto, str, e)
741 }
742 if e = putScriptAddress(
743 ns, &s.scope, a.AddrHash(), ImportedAddrAccount, ssNone, encryptedHash,
744 a.scriptEncrypted,
745 ); E.Chk(e) {
746 return nil, maybeConvertDbError(e)
747 }
748 }
749 }
750 // Finally update the next address tracking and add the addresses to the cache
751 // after the newly generated addresses have been successfully added to the db.
752 managedAddresses := make([]ManagedAddress, 0, len(addressInfo))
753 for _, info := range addressInfo {
754 ma := info.managedAddr
755 s.addrs[addrKey(ma.Address().ScriptAddress())] = ma
756 // Add the new managed address to the list of addresses that need their private
757 // keys derived when the address manager is next unlocked.
758 if s.rootManager.IsLocked() && !s.rootManager.WatchOnly() {
759 s.deriveOnUnlock = append(s.deriveOnUnlock, info)
760 }
761 managedAddresses = append(managedAddresses, ma)
762 }
763 // Set the last address and next address for tracking.
764 ma := addressInfo[len(addressInfo)-1].managedAddr
765 if internal {
766 acctInfo.nextInternalIndex = nextIndex
767 acctInfo.lastInternalAddr = ma
768 } else {
769 acctInfo.nextExternalIndex = nextIndex
770 acctInfo.lastExternalAddr = ma
771 }
772 return managedAddresses, nil
773 }
774 775 // extendAddresses ensures that all addresses up to and including the lastIndex
776 // are derived for either an internal or external branch. If the child at
777 // lastIndex is invalid, this method will proceed until the next valid child is
778 // found. An error is returned if method failed to properly extend addresses up
779 // to the requested index.
780 //
781 // This function MUST be called with the manager lock held for writes.
782 func (s *ScopedKeyManager) extendAddresses(
783 ns walletdb.ReadWriteBucket,
784 account uint32, lastIndex uint32, internal bool,
785 ) (e error) {
786 // The next address can only be generated for accounts that have already been
787 // created.
788 var acctInfo *accountInfo
789 if acctInfo, e = s.loadAccountInfo(ns, account); E.Chk(e) {
790 return e
791 }
792 // Choose the account key to used based on whether the address manager is
793 // locked.
794 acctKey := acctInfo.acctKeyPub
795 if !s.rootManager.IsLocked() {
796 acctKey = acctInfo.acctKeyPriv
797 }
798 // Choose the branch key and index depending on whether or not this is an
799 // internal address.
800 branchNum, nextIndex := ExternalBranch, acctInfo.nextExternalIndex
801 if internal {
802 branchNum = InternalBranch
803 nextIndex = acctInfo.nextInternalIndex
804 }
805 addrType := s.addrSchema.ExternalAddrType
806 if internal {
807 addrType = s.addrSchema.InternalAddrType
808 }
809 // If the last index requested is already lower than the next index, we can
810 // return early.
811 if lastIndex < nextIndex {
812 return nil
813 }
814 // Ensure the requested number of addresses doesn't exceed the maximum allowed
815 // for this account.
816 if lastIndex > MaxAddressesPerAccount {
817 str := fmt.Sprintf(
818 "last index %d would exceed the maximum "+
819 "allowed number of addresses per account of %d",
820 lastIndex, MaxAddressesPerAccount,
821 )
822 return managerError(ErrTooManyAddresses, str, nil)
823 }
824 // Derive the appropriate branch key and ensure it is zeroed when done.
825 var branchKey *hdkeychain.ExtendedKey
826 if branchKey, e = acctKey.Child(branchNum); E.Chk(e) {
827 str := fmt.Sprintf("failed to derive extended key branch %d", branchNum)
828 return managerError(ErrKeyChain, str, e)
829 }
830 defer branchKey.Zero() // Ensure branch key is zeroed when done.
831 // Starting from this branch's nextIndex, derive all child indexes up to and
832 // including the requested lastIndex. If a invalid child is detected, this loop
833 // will continue deriving until it finds the next subsequent index.
834 addressInfo := make([]*unlockDeriveInfo, 0, lastIndex-nextIndex)
835 for nextIndex <= lastIndex {
836 // There is an extremely small chance that a particular child is invalid, so use
837 // a loop to derive the next valid child.
838 var nextKey *hdkeychain.ExtendedKey
839 for {
840 // Derive the next child in the external chain branch.
841 var key *hdkeychain.ExtendedKey
842 if key, e = branchKey.Child(nextIndex); E.Chk(e) {
843 // When this particular child is invalid, skip to the next index.
844 if e == hdkeychain.ErrInvalidChild {
845 nextIndex++
846 continue
847 }
848 str := fmt.Sprintf(
849 "failed to generate child %d",
850 nextIndex,
851 )
852 return managerError(ErrKeyChain, str, e)
853 }
854 key.SetNet(s.rootManager.chainParams)
855 nextIndex++
856 nextKey = key
857 break
858 }
859 // Now that we know this key can be used, we'll create the proper derivation
860 // path so this information can be available to callers.
861 derivationPath := DerivationPath{
862 Account: account,
863 Branch: branchNum,
864 Index: nextIndex - 1,
865 }
866 // Create a new managed address based on the public or private key depending on
867 // whether the generated key is private. Also, zero the next key after creating
868 // the managed address from it.
869 var managedAddr *managedAddress
870 if managedAddr, e = newManagedAddressFromExtKey(s, derivationPath, nextKey, addrType); E.Chk(e) {
871 return e
872 }
873 if internal {
874 managedAddr.internal = true
875 }
876 nextKey.Zero()
877 info := unlockDeriveInfo{
878 managedAddr: managedAddr,
879 branch: branchNum,
880 index: nextIndex - 1,
881 }
882 addressInfo = append(addressInfo, &info)
883 }
884 // Now that all addresses have been successfully generated, update the database
885 // in a single transaction.
886 for _, info := range addressInfo {
887 ma := info.managedAddr
888 addressID := ma.Address().ScriptAddress()
889 switch a := ma.(type) {
890 case *managedAddress:
891 if e = putChainedAddress(
892 ns, &s.scope, addressID, account, ssFull,
893 info.branch, info.index, adtChain,
894 ); E.Chk(e) {
895 return maybeConvertDbError(e)
896 }
897 case *scriptAddress:
898 var encryptedHash []byte
899 if encryptedHash, e = s.rootManager.cryptoKeyPub.Encrypt(a.AddrHash()); E.Chk(e) {
900 str := fmt.Sprintf(
901 "failed to encrypt script hash %x",
902 a.AddrHash(),
903 )
904 return managerError(ErrCrypto, str, e)
905 }
906 if e = putScriptAddress(
907 ns, &s.scope, a.AddrHash(), ImportedAddrAccount,
908 ssNone, encryptedHash, a.scriptEncrypted,
909 ); E.Chk(e) {
910 return maybeConvertDbError(e)
911 }
912 }
913 }
914 // Finally update the next address tracking and add the addresses to the cache
915 // after the newly generated addresses have been successfully added to the db.
916 for _, info := range addressInfo {
917 ma := info.managedAddr
918 s.addrs[addrKey(ma.Address().ScriptAddress())] = ma
919 // Add the new managed address to the list of addresses that need their private
920 // keys derived when the address manager is next unlocked.
921 if s.rootManager.IsLocked() && !s.rootManager.WatchOnly() {
922 s.deriveOnUnlock = append(s.deriveOnUnlock, info)
923 }
924 }
925 // Set the last address and next address for tracking.
926 ma := addressInfo[len(addressInfo)-1].managedAddr
927 if internal {
928 acctInfo.nextInternalIndex = nextIndex
929 acctInfo.lastInternalAddr = ma
930 } else {
931 acctInfo.nextExternalIndex = nextIndex
932 acctInfo.lastExternalAddr = ma
933 }
934 return nil
935 }
936 937 // NextExternalAddresses returns the specified number of next chained addresses
938 // that are intended for external use from the address manager.
939 func (s *ScopedKeyManager) NextExternalAddresses(
940 ns walletdb.ReadWriteBucket,
941 account uint32, numAddresses uint32,
942 ) (ma []ManagedAddress, e error) {
943 // Enforce maximum account number.
944 if account > MaxAccountNum {
945 if e = managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil); E.Chk(e) {
946 }
947 return nil, e
948 }
949 s.mtx.Lock()
950 defer s.mtx.Unlock()
951 return s.nextAddresses(ns, account, numAddresses, false)
952 }
953 954 // NextInternalAddresses returns the specified number of next chained addresses
955 // that are intended for internal use such as change from the address manager.
956 func (s *ScopedKeyManager) NextInternalAddresses(
957 ns walletdb.ReadWriteBucket,
958 account uint32, numAddresses uint32,
959 ) (ma []ManagedAddress, e error) {
960 // Enforce maximum account number.
961 if account > MaxAccountNum {
962 if e = managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil); E.Chk(e) {
963 }
964 return nil, e
965 }
966 s.mtx.Lock()
967 defer s.mtx.Unlock()
968 return s.nextAddresses(ns, account, numAddresses, true)
969 }
970 971 // ExtendExternalAddresses ensures that all valid external keys through
972 // lastIndex are derived and stored in the wallet. This is used to ensure that
973 // wallet's persistent state catches up to a external child that was found
974 // during recovery.
975 func (s *ScopedKeyManager) ExtendExternalAddresses(
976 ns walletdb.ReadWriteBucket,
977 account uint32, lastIndex uint32,
978 ) (e error) {
979 if account > MaxAccountNum {
980 if e = managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil); E.Chk(e) {
981 }
982 return e
983 }
984 s.mtx.Lock()
985 defer s.mtx.Unlock()
986 return s.extendAddresses(ns, account, lastIndex, false)
987 }
988 989 // ExtendInternalAddresses ensures that all valid internal keys through
990 // lastIndex are derived and stored in the wallet. This is used to ensure that
991 // wallet's persistent state catches up to an internal child that was found
992 // during recovery.
993 func (s *ScopedKeyManager) ExtendInternalAddresses(
994 ns walletdb.ReadWriteBucket,
995 account uint32, lastIndex uint32,
996 ) (e error) {
997 if account > MaxAccountNum {
998 e = managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil)
999 return e
1000 }
1001 s.mtx.Lock()
1002 defer s.mtx.Unlock()
1003 return s.extendAddresses(ns, account, lastIndex, true)
1004 }
1005 1006 // LastExternalAddress returns the most recently requested chained external
1007 // address from calling NextExternalAddress for the given account. The first
1008 // external address for the account will be returned if none have been
1009 // previously requested.
1010 //
1011 // This function will return an error if the provided account number is greater
1012 // than the MaxAccountNum constant or there is no account information for the
1013 // passed account. Any other errors returned are generally unexpected.
1014 func (s *ScopedKeyManager) LastExternalAddress(
1015 ns walletdb.ReadBucket,
1016 account uint32,
1017 ) (ManagedAddress, error) {
1018 // Enforce maximum account number.
1019 if account > MaxAccountNum {
1020 return nil, managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil)
1021 }
1022 s.mtx.Lock()
1023 defer s.mtx.Unlock()
1024 // Load account information for the passed account. It is typically cached, but
1025 // if not it will be loaded from the database.
1026 var e error
1027 var acctInfo *accountInfo
1028 if acctInfo, e = s.loadAccountInfo(ns, account); E.Chk(e) {
1029 return nil, e
1030 }
1031 if acctInfo.nextExternalIndex > 0 {
1032 return acctInfo.lastExternalAddr, nil
1033 }
1034 return nil, managerError(ErrAddressNotFound, "no previous external address", nil)
1035 }
1036 1037 // LastInternalAddress returns the most recently requested chained internal
1038 // address from calling NextInternalAddress for the given account. The first
1039 // internal address for the account will be returned if none have been
1040 // previously requested.
1041 //
1042 // This function will return an error if the provided account number is greater
1043 // than the MaxAccountNum constant or there is no account information for the
1044 // passed account. Any other errors returned are generally unexpected.
1045 func (s *ScopedKeyManager) LastInternalAddress(
1046 ns walletdb.ReadBucket,
1047 account uint32,
1048 ) (ManagedAddress, error) {
1049 // Enforce maximum account number.
1050 if account > MaxAccountNum {
1051 e := managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil)
1052 return nil, e
1053 }
1054 s.mtx.Lock()
1055 defer s.mtx.Unlock()
1056 // Load account information for the passed account. It is typically cached, but
1057 // if not it will be loaded from the database.
1058 var acctInfo *accountInfo
1059 var e error
1060 if acctInfo, e = s.loadAccountInfo(ns, account); E.Chk(e) {
1061 return nil, e
1062 }
1063 if acctInfo.nextInternalIndex > 0 {
1064 return acctInfo.lastInternalAddr, nil
1065 }
1066 return nil, managerError(ErrAddressNotFound, "no previous internal address", nil)
1067 }
1068 1069 // NewRawAccount creates a new account for the scoped manager. This method
1070 // differs from the NewAccount method in that this method takes the acount
1071 // number *directly*, rather than taking a string name for the account, then
1072 // mapping that to the next highest account number.
1073 func (s *ScopedKeyManager) NewRawAccount(ns walletdb.ReadWriteBucket, number uint32) (e error) {
1074 if s.rootManager.WatchOnly() {
1075 return managerError(ErrWatchingOnly, errWatchingOnly, nil)
1076 }
1077 s.mtx.Lock()
1078 defer s.mtx.Unlock()
1079 if s.rootManager.IsLocked() {
1080 return managerError(ErrLocked, errLocked, nil)
1081 }
1082 // As this is an ad hoc account that may not follow our normal linear
1083 // derivation, we'll create a new name for this account based off of the account
1084 // number.
1085 name := fmt.Sprintf("act:%v", number)
1086 return s.newAccount(ns, number, name)
1087 }
1088 1089 // NewAccount creates and returns a new account stored in the manager based on
1090 // the given account name. If an account with the same name already exists,
1091 // ErrDuplicateAccount will be returned. Since creating a new account requires
1092 // access to the cointype keys (from which extended account keys are derived),
1093 // it requires the manager to be unlocked.
1094 func (s *ScopedKeyManager) NewAccount(ns walletdb.ReadWriteBucket, name string) (account uint32, e error) {
1095 if s.rootManager.WatchOnly() {
1096 return 0, managerError(ErrWatchingOnly, errWatchingOnly, nil)
1097 }
1098 s.mtx.Lock()
1099 defer s.mtx.Unlock()
1100 if s.rootManager.IsLocked() {
1101 return 0, managerError(ErrLocked, errLocked, nil)
1102 }
1103 // Fetch latest account, and create a new account in the same transaction Fetch
1104 // the latest account number to generate the next account number
1105 if account, e = fetchLastAccount(ns, &s.scope); E.Chk(e) {
1106 return 0, e
1107 }
1108 account++
1109 // With the name validated, we'll create a new account for the new contiguous account.
1110 if e := s.newAccount(ns, account, name); E.Chk(e) {
1111 return 0, e
1112 }
1113 return account, nil
1114 }
1115 1116 // newAccount is a helper function that derives a new precise account number,
1117 // and creates a mapping from the passed name to the account number in the
1118 // database.
1119 //
1120 // NOTE: This function MUST be called with the manager lock held for writes.
1121 func (s *ScopedKeyManager) newAccount(
1122 ns walletdb.ReadWriteBucket,
1123 account uint32, name string,
1124 ) (e error) {
1125 // Validate the account name.
1126 if e = ValidateAccountName(name); E.Chk(e) {
1127 return e
1128 }
1129 // Chk that account with the same name does not exist
1130 if _, e = s.lookupAccount(ns, name); E.Chk(e) {
1131 str := fmt.Sprintf("account with the same name already exists")
1132 return managerError(ErrDuplicateAccount, str, e)
1133 }
1134 // Fetch the cointype key which will be used to derive the next account extended
1135 // keys
1136 var coinTypePrivEnc []byte
1137 if _, coinTypePrivEnc, e = fetchCoinTypeKeys(ns, &s.scope); E.Chk(e) {
1138 return e
1139 }
1140 // Decrypt the cointype key.
1141 var serializedKeyPriv []byte
1142 if serializedKeyPriv, e = s.rootManager.cryptoKeyPriv.Decrypt(coinTypePrivEnc); E.Chk(e) {
1143 str := fmt.Sprintf("failed to decrypt cointype serialized private key")
1144 return managerError(ErrLocked, str, e)
1145 }
1146 var coinTypeKeyPriv *hdkeychain.ExtendedKey
1147 if coinTypeKeyPriv, e = hdkeychain.NewKeyFromString(string(serializedKeyPriv)); E.Chk(e) {
1148 zero.Bytes(serializedKeyPriv)
1149 str := fmt.Sprintf("failed to create cointype extended private key")
1150 return managerError(ErrKeyChain, str, e)
1151 }
1152 zero.Bytes(serializedKeyPriv)
1153 // Derive the account key using the cointype key
1154 var acctKeyPriv *hdkeychain.ExtendedKey
1155 if acctKeyPriv, e = deriveAccountKey(coinTypeKeyPriv, account); E.Chk(e) {
1156 coinTypeKeyPriv.Zero()
1157 str := "failed to convert private key for account"
1158 return managerError(ErrKeyChain, str, e)
1159 }
1160 coinTypeKeyPriv.Zero()
1161 var acctKeyPub *hdkeychain.ExtendedKey
1162 if acctKeyPub, e = acctKeyPriv.Neuter(); E.Chk(e) {
1163 str := "failed to convert public key for account"
1164 return managerError(ErrKeyChain, str, e)
1165 }
1166 // Encrypt the default account keys with the associated crypto keys.
1167 var acctPubEnc []byte
1168 if acctPubEnc, e = s.rootManager.cryptoKeyPub.Encrypt([]byte(acctKeyPub.String())); E.Chk(e) {
1169 str := "failed to encrypt public key for account"
1170 return managerError(ErrCrypto, str, e)
1171 }
1172 var acctPrivEnc []byte
1173 if acctPrivEnc, e = s.rootManager.cryptoKeyPriv.Encrypt([]byte(acctKeyPriv.String())); E.Chk(e) {
1174 str := "failed to encrypt private key for account"
1175 return managerError(ErrCrypto, str, e)
1176 }
1177 // We have the encrypted account extended keys, so save them to the database
1178 if e = putAccountInfo(ns, &s.scope, account, acctPubEnc, acctPrivEnc, 0, 0, name); E.Chk(e) {
1179 return e
1180 }
1181 // Save last account metadata
1182 return putLastAccount(ns, &s.scope, account)
1183 }
1184 1185 // RenameAccount renames an account stored in the manager based on the given
1186 // account number with the given name. If an account with the same name already
1187 // exists, ErrDuplicateAccount will be returned.
1188 func (s *ScopedKeyManager) RenameAccount(
1189 ns walletdb.ReadWriteBucket,
1190 account uint32, name string,
1191 ) (e error) {
1192 s.mtx.Lock()
1193 defer s.mtx.Unlock()
1194 // Ensure that a reserved account is not being renamed.
1195 if isReservedAccountNum(account) {
1196 str := "reserved account cannot be renamed"
1197 return managerError(ErrInvalidAccount, str, nil)
1198 }
1199 // Chk that account with the new name does not exist
1200 _, e = s.lookupAccount(ns, name)
1201 if e == nil {
1202 str := fmt.Sprintf("account with the same name already exists")
1203 return managerError(ErrDuplicateAccount, str, e)
1204 }
1205 // Validate account name
1206 if e = ValidateAccountName(name); E.Chk(e) {
1207 return e
1208 }
1209 var rowInterface interface{}
1210 if rowInterface, e = fetchAccountInfo(ns, &s.scope, account); E.Chk(e) {
1211 return e
1212 }
1213 // Ensure the account type is a default account.
1214 var row *dbDefaultAccountRow
1215 ok := false
1216 if row, ok = rowInterface.(*dbDefaultAccountRow); !ok {
1217 str := fmt.Sprintf("unsupported account type %T", row)
1218 return managerError(ErrDatabase, str, nil)
1219 }
1220 // Remove the old name key from the account id index.
1221 if e = deleteAccountIDIndex(ns, &s.scope, account); E.Chk(e) {
1222 return e
1223 }
1224 // Remove the old name key from the account name index.
1225 if e = deleteAccountNameIndex(ns, &s.scope, row.name); E.Chk(e) {
1226 return e
1227 }
1228 if e = putAccountInfo(
1229 ns, &s.scope, account, row.pubKeyEncrypted,
1230 row.privKeyEncrypted, row.nextExternalIndex,
1231 row.nextInternalIndex, name,
1232 ); E.Chk(e) {
1233 return e
1234 }
1235 // Update in-memory account info with new name if cached and the db write was
1236 // successful.
1237 if acctInfo, ok := s.acctInfo[account]; ok {
1238 acctInfo.acctName = name
1239 }
1240 return e
1241 }
1242 1243 // ImportPrivateKey imports a WIF private key into the address manager. The
1244 // imported address is created using either a compressed or uncompressed
1245 // serialized public key, depending on the CompressPubKey bool of the WIF.
1246 //
1247 // All imported addresses will be part of the account defined by the
1248 // ImportedAddrAccount constant.
1249 //
1250 // NOTE: When the address manager is watching-only, the private key itself will
1251 // not be stored or available since it is private data. Instead, only the public
1252 // key will be stored. This means it is paramount the private key is kept
1253 // elsewhere as the watching-only address manager will NOT ever have access to
1254 // it.
1255 //
1256 // This function will return an error if the address manager is locked and not
1257 // watching-only, or not for the same network as the key trying to be imported.
1258 // It will also return an error if the address already exists. Any other errors
1259 // returned are generally unexpected.
1260 func (s *ScopedKeyManager) ImportPrivateKey(
1261 ns walletdb.ReadWriteBucket,
1262 wif *util.WIF, bs *BlockStamp,
1263 ) (ManagedPubKeyAddress, error) {
1264 // Ensure the address is intended for network the address manager is associated
1265 // with.
1266 if !wif.IsForNet(s.rootManager.chainParams) {
1267 str := fmt.Sprintf(
1268 "private key is not for the same network the "+
1269 "address manager is configured for (%s)",
1270 s.rootManager.chainParams.Name,
1271 )
1272 return nil, managerError(ErrWrongNet, str, nil)
1273 }
1274 s.mtx.Lock()
1275 defer s.mtx.Unlock()
1276 // The manager must be unlocked to encrypt the imported private key.
1277 if s.rootManager.IsLocked() && !s.rootManager.WatchOnly() {
1278 return nil, managerError(ErrLocked, errLocked, nil)
1279 }
1280 // Prevent duplicates.
1281 serializedPubKey := wif.SerializePubKey()
1282 pubKeyHash := btcaddr.Hash160(serializedPubKey)
1283 alreadyExists := s.existsAddress(ns, pubKeyHash)
1284 if alreadyExists {
1285 str := fmt.Sprintf("address for public key %x already exists", serializedPubKey)
1286 return nil, managerError(ErrDuplicateAddress, str, nil)
1287 }
1288 // Encrypt public key.
1289 var encryptedPubKey []byte
1290 var e error
1291 if encryptedPubKey, e = s.rootManager.cryptoKeyPub.Encrypt(serializedPubKey); E.Chk(e) {
1292 str := fmt.Sprintf("failed to encrypt public key for %x", serializedPubKey)
1293 return nil, managerError(ErrCrypto, str, e)
1294 }
1295 // Encrypt the private key when not a watching-only address manager.
1296 var encryptedPrivKey []byte
1297 if !s.rootManager.WatchOnly() {
1298 privKeyBytes := wif.PrivKey.Serialize()
1299 if encryptedPrivKey, e = s.rootManager.cryptoKeyPriv.Encrypt(privKeyBytes); E.Chk(e) {
1300 zero.Bytes(privKeyBytes)
1301 str := fmt.Sprintf("failed to encrypt private key for %x", serializedPubKey)
1302 return nil, managerError(ErrCrypto, str, e)
1303 }
1304 }
1305 // The start block needs to be updated when the newly imported address is before
1306 // the current one.
1307 s.rootManager.mtx.Lock()
1308 updateStartBlock := bs.Height < s.rootManager.syncState.startBlock.Height
1309 s.rootManager.mtx.Unlock()
1310 // Save the new imported address to the db and update start block (if needed) in
1311 // a single transaction.
1312 if e = putImportedAddress(
1313 ns, &s.scope, pubKeyHash, ImportedAddrAccount, ssNone,
1314 encryptedPubKey, encryptedPrivKey,
1315 ); E.Chk(e) {
1316 return nil, e
1317 }
1318 if updateStartBlock {
1319 if e = putStartBlock(ns, bs); E.Chk(e) {
1320 return nil, e
1321 }
1322 }
1323 // Now that the database has been updated, update the start block in memory too
1324 // if needed.
1325 if updateStartBlock {
1326 s.rootManager.mtx.Lock()
1327 s.rootManager.syncState.startBlock = *bs
1328 s.rootManager.mtx.Unlock()
1329 }
1330 // The full derivation path for an imported key is incomplete as we don't know
1331 // exactly how it was derived.
1332 importedDerivationPath := DerivationPath{Account: ImportedAddrAccount}
1333 // Create a new managed address based on the imported address.
1334 var managedAddr *managedAddress
1335 if !s.rootManager.WatchOnly() {
1336 managedAddr, e = newManagedAddress(
1337 s, importedDerivationPath, wif.PrivKey,
1338 wif.CompressPubKey, s.addrSchema.ExternalAddrType,
1339 )
1340 } else {
1341 pubKey := (*ec.PublicKey)(&wif.PrivKey.PublicKey)
1342 managedAddr, e = newManagedAddressWithoutPrivKey(
1343 s, importedDerivationPath, pubKey, wif.CompressPubKey,
1344 s.addrSchema.ExternalAddrType,
1345 )
1346 }
1347 if E.Chk(e) {
1348 return nil, e
1349 }
1350 managedAddr.imported = true
1351 // Add the new managed address to the cache of recent addresses and return it.
1352 s.addrs[addrKey(managedAddr.Address().ScriptAddress())] = managedAddr
1353 return managedAddr, nil
1354 }
1355 1356 // ImportScript imports a user-provided script into the address manager. The
1357 // imported script will act as a pay-to-script-hash address.
1358 //
1359 // All imported script addresses will be part of the account defined by the
1360 // ImportedAddrAccount constant.
1361 //
1362 // When the address manager is watching-only, the script itself will not be
1363 // stored or available since it is considered private data.
1364 //
1365 // This function will return an error if the address manager is locked and not
1366 // watching-only, or the address already exists. Any other errors returned are
1367 // generally unexpected.
1368 func (s *ScopedKeyManager) ImportScript(
1369 ns walletdb.ReadWriteBucket,
1370 script []byte, bs *BlockStamp,
1371 ) (ManagedScriptAddress, error) {
1372 s.mtx.Lock()
1373 defer s.mtx.Unlock()
1374 // The manager must be unlocked to encrypt the imported script.
1375 if s.rootManager.IsLocked() && !s.rootManager.WatchOnly() {
1376 return nil, managerError(ErrLocked, errLocked, nil)
1377 }
1378 // Prevent duplicates.
1379 scriptHash := btcaddr.Hash160(script)
1380 alreadyExists := s.existsAddress(ns, scriptHash)
1381 if alreadyExists {
1382 str := fmt.Sprintf(
1383 "address for script hash %x already exists",
1384 scriptHash,
1385 )
1386 return nil, managerError(ErrDuplicateAddress, str, nil)
1387 }
1388 // Encrypt the script hash using the crypto public key so it is accessible when
1389 // the address manager is locked or watching-only.
1390 var encryptedHash []byte
1391 var e error
1392 if encryptedHash, e = s.rootManager.cryptoKeyPub.Encrypt(scriptHash); E.Chk(e) {
1393 str := fmt.Sprintf("failed to encrypt script hash %x", scriptHash)
1394 return nil, managerError(ErrCrypto, str, e)
1395 }
1396 // Encrypt the script for storage in database using the crypto script key when
1397 // not a watching-only address manager.
1398 var encryptedScript []byte
1399 if !s.rootManager.WatchOnly() {
1400 if encryptedScript, e = s.rootManager.cryptoKeyScript.Encrypt(
1401 script,
1402 ); E.Chk(e) {
1403 str := fmt.Sprintf("failed to encrypt script for %x", scriptHash)
1404 return nil, managerError(ErrCrypto, str, e)
1405 }
1406 }
1407 // The start block needs to be updated when the newly imported address is before
1408 // the current one.
1409 updateStartBlock := false
1410 s.rootManager.mtx.Lock()
1411 if bs.Height < s.rootManager.syncState.startBlock.Height {
1412 updateStartBlock = true
1413 }
1414 s.rootManager.mtx.Unlock()
1415 // Save the new imported address to the db and update start block (if needed) in
1416 // a single transaction.
1417 if e = putScriptAddress(
1418 ns, &s.scope, scriptHash, ImportedAddrAccount, ssNone,
1419 encryptedHash, encryptedScript,
1420 ); E.Chk(e) {
1421 return nil, maybeConvertDbError(e)
1422 }
1423 if updateStartBlock {
1424 if e = putStartBlock(ns, bs); E.Chk(e) {
1425 return nil, maybeConvertDbError(e)
1426 }
1427 }
1428 // Now that the database has been updated, update the start block in memory too
1429 // if needed.
1430 if updateStartBlock {
1431 s.rootManager.mtx.Lock()
1432 s.rootManager.syncState.startBlock = *bs
1433 s.rootManager.mtx.Unlock()
1434 }
1435 // Create a new managed address based on the imported script. Also, when not a
1436 // watching-only address manager, make a copy of the script since it will be
1437 // cleared on lock and the script the caller passed should not be cleared out
1438 // from under the caller.
1439 var scriptAddr *scriptAddress
1440 if scriptAddr, e = newScriptAddress(s, ImportedAddrAccount, scriptHash, encryptedScript); E.Chk(e) {
1441 return nil, e
1442 }
1443 if !s.rootManager.WatchOnly() {
1444 scriptAddr.scriptCT = make([]byte, len(script))
1445 copy(scriptAddr.scriptCT, script)
1446 }
1447 // Add the new managed address to the cache of recent addresses and return it.
1448 s.addrs[addrKey(scriptHash)] = scriptAddr
1449 return scriptAddr, nil
1450 }
1451 1452 // lookupAccount loads account number stored in the manager for the given
1453 // account name
1454 //
1455 // This function MUST be called with the manager lock held for reads.
1456 func (s *ScopedKeyManager) lookupAccount(ns walletdb.ReadBucket, name string) (uint32, error) {
1457 return fetchAccountByName(ns, &s.scope, name)
1458 }
1459 1460 // LookupAccount loads account number stored in the manager for the given account name
1461 func (s *ScopedKeyManager) LookupAccount(ns walletdb.ReadBucket, name string) (uint32, error) {
1462 s.mtx.RLock()
1463 defer s.mtx.RUnlock()
1464 return s.lookupAccount(ns, name)
1465 }
1466 1467 // fetchUsed returns true if the provided address id was flagged used.
1468 func (s *ScopedKeyManager) fetchUsed(
1469 ns walletdb.ReadBucket,
1470 addressID []byte,
1471 ) bool {
1472 return fetchAddressUsed(ns, &s.scope, addressID)
1473 }
1474 1475 // MarkUsed updates the used flag for the provided address.
1476 func (s *ScopedKeyManager) MarkUsed(
1477 ns walletdb.ReadWriteBucket,
1478 address btcaddr.Address,
1479 ) (e error) {
1480 addressID := address.ScriptAddress()
1481 if e = markAddressUsed(ns, &s.scope, addressID); E.Chk(e) {
1482 return maybeConvertDbError(e)
1483 }
1484 // Clear caches which might have stale entries for used addresses
1485 s.mtx.Lock()
1486 delete(s.addrs, addrKey(addressID))
1487 s.mtx.Unlock()
1488 return nil
1489 }
1490 1491 // ChainParams returns the chain parameters for this address manager.
1492 func (s *ScopedKeyManager) ChainParams() *chaincfg.Params {
1493 // NOTE: No need for mutex here since the net field does not change after the
1494 // manager instance is created.
1495 return s.rootManager.chainParams
1496 }
1497 1498 // AccountName returns the account name for the given account number stored in
1499 // the manager.
1500 func (s *ScopedKeyManager) AccountName(ns walletdb.ReadBucket, account uint32) (string, error) {
1501 return fetchAccountName(ns, &s.scope, account)
1502 }
1503 1504 // ForEachAccount calls the given function with each account stored in the
1505 // manager, breaking early on error.
1506 func (s *ScopedKeyManager) ForEachAccount(
1507 ns walletdb.ReadBucket,
1508 fn func(account uint32) error,
1509 ) (e error) {
1510 return forEachAccount(ns, &s.scope, fn)
1511 }
1512 1513 // LastAccount returns the last account stored in the manager.
1514 func (s *ScopedKeyManager) LastAccount(ns walletdb.ReadBucket) (uint32, error) {
1515 return fetchLastAccount(ns, &s.scope)
1516 }
1517 1518 // ForEachAccountAddress calls the given function with each address of the given
1519 // account stored in the manager, breaking early on error.
1520 func (s *ScopedKeyManager) ForEachAccountAddress(
1521 ns walletdb.ReadBucket,
1522 account uint32, fn func(maddr ManagedAddress) error,
1523 ) (e error) {
1524 s.mtx.Lock()
1525 defer s.mtx.Unlock()
1526 addrFn := func(rowInterface interface{}) (e error) {
1527 var managedAddr ManagedAddress
1528 if managedAddr, e = s.rowInterfaceToManaged(ns, rowInterface); E.Chk(e) {
1529 return e
1530 }
1531 return fn(managedAddr)
1532 }
1533 if e = forEachAccountAddress(ns, &s.scope, account, addrFn); E.Chk(e) {
1534 return maybeConvertDbError(e)
1535 }
1536 return nil
1537 }
1538 1539 // ForEachActiveAccountAddress calls the given function with each active address
1540 // of the given account stored in the manager, breaking early on error.
1541 //
1542 // TODO(tuxcanfly): actually return only active addresses
1543 func (s *ScopedKeyManager) ForEachActiveAccountAddress(
1544 ns walletdb.ReadBucket, account uint32,
1545 fn func(maddr ManagedAddress) error,
1546 ) (e error) {
1547 return s.ForEachAccountAddress(ns, account, fn)
1548 }
1549 1550 // ForEachActiveAddress calls the given function with each active address stored
1551 // in the manager, breaking early on error.
1552 func (s *ScopedKeyManager) ForEachActiveAddress(
1553 ns walletdb.ReadBucket,
1554 fn func(addr btcaddr.Address) error,
1555 ) (e error) {
1556 s.mtx.Lock()
1557 defer s.mtx.Unlock()
1558 addrFn := func(rowInterface interface{}) (e error) {
1559 var managedAddr ManagedAddress
1560 if managedAddr, e = s.rowInterfaceToManaged(ns, rowInterface); E.Chk(e) {
1561 return e
1562 }
1563 return fn(managedAddr.Address())
1564 }
1565 if e = forEachActiveAddress(ns, &s.scope, addrFn); E.Chk(e) {
1566 return maybeConvertDbError(e)
1567 }
1568 return nil
1569 }
1570