decred.org/dcrwallet/v3@v3.1.0/wallet/addresses.go (about) 1 // Copyright (c) 2017-2020 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package wallet 6 7 import ( 8 "context" 9 "encoding/binary" 10 "runtime/trace" 11 12 "decred.org/dcrwallet/v3/errors" 13 "decred.org/dcrwallet/v3/internal/compat" 14 "decred.org/dcrwallet/v3/wallet/txsizes" 15 "decred.org/dcrwallet/v3/wallet/udb" 16 "decred.org/dcrwallet/v3/wallet/walletdb" 17 "github.com/decred/dcrd/chaincfg/v3" 18 "github.com/decred/dcrd/dcrutil/v4" 19 "github.com/decred/dcrd/hdkeychain/v3" 20 "github.com/decred/dcrd/txscript/v4" 21 "github.com/decred/dcrd/txscript/v4/stdaddr" 22 ) 23 24 // AccountKind describes the purpose and type of a wallet account. 25 type AccountKind int 26 27 const ( 28 // AccountKindBIP0044 describes a BIP0044 account derived from the 29 // wallet seed. New addresses created from the account encode secp256k1 30 // P2PKH output scripts. 31 AccountKindBIP0044 AccountKind = iota 32 33 // AccountKindImported describes an account with only singular, possibly 34 // unrelated imported keys. Keys must be manually reimported after seed 35 // restore. New addresses can not be derived from the account. 36 AccountKindImported 37 38 // AccountKindImportedXpub describes a BIP0044 account created from an 39 // imported extended key. It operates like a seed-derived BIP0044 40 // account. 41 AccountKindImportedXpub 42 ) 43 44 // Address is a human-readable encoding of an output script. 45 // 46 // Address encodings may include a network identifier, to prevent misuse on an 47 // alternate Decred network. 48 type Address interface { 49 String() string 50 51 // PaymentScript returns the output script and script version to pay the 52 // address. The version is always returned with the script, as it is 53 // not useful to use the script without the version. 54 PaymentScript() (version uint16, script []byte) 55 56 // ScriptLen returns the known length of the address output script. 57 ScriptLen() int 58 } 59 60 // KnownAddress represents an address recorded by the wallet. It is potentially 61 // watched for involving transactions during wallet syncs. 62 type KnownAddress interface { 63 Address 64 65 // AccountName returns the account name associated with the known 66 // address. 67 AccountName() string 68 69 // AccountKind describes the kind or purpose of the address' account. 70 AccountKind() AccountKind 71 } 72 73 // PubKeyHashAddress is a KnownAddress for a secp256k1 pay-to-pubkey-hash 74 // (P2PKH) output script. 75 type PubKeyHashAddress interface { 76 KnownAddress 77 78 // PubKey returns the serialized compressed public key. This key must 79 // be included in scripts redeeming P2PKH outputs paying the address. 80 PubKey() []byte 81 82 // PubKeyHash returns the hashed compressed public key. This hash must 83 // appear in output scripts paying to the address. 84 PubKeyHash() []byte 85 } 86 87 // BIP0044Address is a KnownAddress for a secp256k1 pay-to-pubkey-hash output, 88 // with keys created from a derived or imported BIP0044 account extended pubkey. 89 type BIP0044Address interface { 90 PubKeyHashAddress 91 92 // Path returns the BIP0032 indexes to derive the BIP0044 address from 93 // the coin type key. The account index is always the non-hardened 94 // identifier, with values between 0 through 1<<31 - 1 (inclusive). The 95 // account index will always be zero if this address belongs to an 96 // imported xpub or imported xpriv account. 97 Path() (account, branch, child uint32) 98 } 99 100 // P2SHAddress is a KnownAddress which pays to the hash of an arbitrary script. 101 type P2SHAddress interface { 102 KnownAddress 103 104 // RedeemScript returns the preimage of the script hash. The returned 105 // version is the script version of the address, or the script version 106 // of the redeemed previous output, and must be used for any operations 107 // involving the script. 108 RedeemScript() (version uint16, script []byte) 109 } 110 111 // managedAddress implements KnownAddress for a wrapped udb.ManagedAddress. 112 type managedAddress struct { 113 acct string 114 acctKind AccountKind 115 addr udb.ManagedAddress 116 script func() (uint16, []byte) 117 scriptLen int 118 } 119 120 func (m *managedAddress) String() string { return m.addr.Address().String() } 121 func (m *managedAddress) PaymentScript() (uint16, []byte) { return m.script() } 122 func (m *managedAddress) ScriptLen() int { return m.scriptLen } 123 func (m *managedAddress) AccountName() string { return m.acct } 124 func (m *managedAddress) AccountKind() AccountKind { return m.acctKind } 125 126 // Possible implementations of m.script 127 func (m *managedAddress) p2pkhScript() (uint16, []byte) { 128 pkh := m.addr.(udb.ManagedPubKeyAddress).AddrHash() 129 s := []byte{ 130 0: txscript.OP_DUP, 131 1: txscript.OP_HASH160, 132 2: txscript.OP_DATA_20, 133 23: txscript.OP_EQUALVERIFY, 134 24: txscript.OP_CHECKSIG, 135 } 136 copy(s[3:23], pkh) 137 return 0, s 138 } 139 func (m *managedAddress) p2shScript() (uint16, []byte) { 140 sh := m.addr.(udb.ManagedScriptAddress).AddrHash() 141 s := []byte{ 142 0: txscript.OP_HASH160, 143 1: txscript.OP_DATA_20, 144 22: txscript.OP_EQUAL, 145 } 146 copy(s[2:22], sh) 147 return 0, s 148 } 149 150 // managedP2PKHAddress implements PubKeyHashAddress for a wrapped udb.ManagedAddress. 151 type managedP2PKHAddress struct { 152 managedAddress 153 } 154 155 func (m *managedP2PKHAddress) PubKey() []byte { 156 return m.addr.(udb.ManagedPubKeyAddress).PubKey() 157 } 158 func (m *managedP2PKHAddress) PubKeyHash() []byte { 159 return m.addr.(udb.ManagedPubKeyAddress).AddrHash() 160 } 161 162 // managedBIP0044Address implements BIP0044Address for a wrapped udb.ManagedAddress. 163 type managedBIP0044Address struct { 164 managedP2PKHAddress 165 account, branch, child uint32 166 } 167 168 func (m *managedBIP0044Address) Path() (account, branch, child uint32) { 169 return m.account, m.branch, m.child 170 } 171 172 // managedP2SHAddress implements P2SHAddress for a wrapped udb.ManagedAddress. 173 type managedP2SHAddress struct { 174 managedAddress 175 } 176 177 func (m *managedP2SHAddress) RedeemScript() (uint16, []byte) { 178 return m.addr.(udb.ManagedScriptAddress).RedeemScript() 179 } 180 181 func wrapManagedAddress(addr udb.ManagedAddress, account string, kind AccountKind) (KnownAddress, error) { 182 ma := managedAddress{ 183 acct: account, 184 acctKind: kind, 185 addr: addr, 186 } 187 switch a := addr.(type) { 188 case udb.ManagedPubKeyAddress: 189 ma.script = ma.p2pkhScript 190 ma.scriptLen = 25 191 192 if kind == AccountKindImported { 193 return &managedP2PKHAddress{ma}, nil 194 } 195 196 var acctNum, branch uint32 197 if kind == AccountKindBIP0044 { 198 acctNum = a.Account() 199 } 200 if a.Internal() { 201 branch = 1 202 } 203 return &managedBIP0044Address{ 204 managedP2PKHAddress: managedP2PKHAddress{ma}, 205 account: acctNum, 206 branch: branch, 207 child: a.Index(), 208 }, nil 209 case udb.ManagedScriptAddress: 210 ma.script = ma.p2shScript 211 ma.scriptLen = 23 212 return &managedP2SHAddress{ma}, nil 213 default: 214 err := errors.Errorf("don't know how to wrap %T", a) 215 return nil, errors.E(errors.Bug, err) 216 } 217 } 218 219 // KnownAddress returns the KnownAddress implementation for an address. The 220 // returned address may implement other interfaces (such as, but not limited to, 221 // PubKeyHashAddress, BIP0044Address, or P2SHAddress) depending on the script 222 // type and account for the address. 223 func (w *Wallet) KnownAddress(ctx context.Context, a stdaddr.Address) (KnownAddress, error) { 224 const op errors.Op = "wallet.KnownAddress" 225 226 var ma udb.ManagedAddress 227 var acct uint32 228 var acctName string 229 err := walletdb.View(ctx, w.db, func(tx walletdb.ReadTx) error { 230 addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey) 231 var err error 232 ma, err = w.manager.Address(addrmgrNs, a) 233 if err != nil { 234 return err 235 } 236 acct = ma.Account() 237 acctName, err = w.manager.AccountName(addrmgrNs, acct) 238 return err 239 }) 240 if err != nil { 241 return nil, errors.E(op, err) 242 } 243 244 var acctKind AccountKind 245 switch { 246 case acct < udb.ImportedAddrAccount: 247 acctKind = AccountKindBIP0044 248 case acct == udb.ImportedAddrAccount: 249 acctKind = AccountKindImported 250 default: 251 acctKind = AccountKindImportedXpub 252 } 253 return wrapManagedAddress(ma, acctName, acctKind) 254 } 255 256 type stakeAddress interface { 257 voteRights() (script []byte, version uint16) 258 ticketChange() (script []byte, version uint16) 259 rewardCommitment(amount dcrutil.Amount, limits uint16) (script []byte, version uint16) 260 payVoteCommitment() (script []byte, version uint16) 261 payRevokeCommitment() (script []byte, version uint16) 262 } 263 264 type xpubAddress struct { 265 *stdaddr.AddressPubKeyHashEcdsaSecp256k1V0 266 xpub *hdkeychain.ExtendedKey 267 accountName string 268 account uint32 269 branch uint32 270 child uint32 271 } 272 273 var _ BIP0044Address = (*xpubAddress)(nil) 274 var _ stakeAddress = (*xpubAddress)(nil) 275 276 func (x *xpubAddress) PaymentScript() (uint16, []byte) { 277 s := []byte{ 278 0: txscript.OP_DUP, 279 1: txscript.OP_HASH160, 280 2: txscript.OP_DATA_20, 281 23: txscript.OP_EQUALVERIFY, 282 24: txscript.OP_CHECKSIG, 283 } 284 copy(s[3:23], x.Hash160()[:]) 285 return 0, s 286 } 287 288 func (x *xpubAddress) ScriptLen() int { return txsizes.P2PKHPkScriptSize } 289 func (x *xpubAddress) AccountName() string { return x.accountName } 290 291 func (x *xpubAddress) AccountKind() AccountKind { 292 if x.account > udb.ImportedAddrAccount { 293 return AccountKindImportedXpub 294 } 295 return AccountKindBIP0044 296 } 297 func (x *xpubAddress) Path() (account, branch, child uint32) { 298 account, branch, child = x.account, x.branch, x.child 299 if x.account > udb.ImportedAddrAccount { 300 account = 0 301 } 302 return 303 } 304 305 func (x *xpubAddress) PubKey() []byte { 306 // All errors are unexpected, since the P2PKH address must have already 307 // been created from the same path. 308 branchKey, err := x.xpub.Child(x.branch) 309 if err != nil { 310 panic(err) 311 } 312 childKey, err := branchKey.Child(x.child) 313 if err != nil { 314 panic(err) 315 } 316 return childKey.SerializedPubKey() 317 } 318 319 func (x *xpubAddress) PubKeyHash() []byte { return x.Hash160()[:] } 320 321 func (x *xpubAddress) voteRights() (script []byte, version uint16) { 322 s := []byte{ 323 0: txscript.OP_SSTX, 324 1: txscript.OP_DUP, 325 2: txscript.OP_HASH160, 326 3: txscript.OP_DATA_20, 327 24: txscript.OP_EQUALVERIFY, 328 25: txscript.OP_CHECKSIG, 329 } 330 copy(s[4:24], x.PubKeyHash()) 331 return s, 0 332 } 333 334 func (x *xpubAddress) ticketChange() (script []byte, version uint16) { 335 s := []byte{ 336 0: txscript.OP_SSTXCHANGE, 337 1: txscript.OP_DUP, 338 2: txscript.OP_HASH160, 339 3: txscript.OP_DATA_20, 340 24: txscript.OP_EQUALVERIFY, 341 25: txscript.OP_CHECKSIG, 342 } 343 copy(s[4:24], x.PubKeyHash()) 344 return s, 0 345 } 346 347 func (x *xpubAddress) rewardCommitment(amount dcrutil.Amount, limits uint16) ([]byte, uint16) { 348 s := make([]byte, 32) 349 s[0] = txscript.OP_RETURN 350 s[1] = txscript.OP_DATA_30 351 copy(s[2:22], x.PubKeyHash()) 352 binary.LittleEndian.PutUint64(s[22:30], uint64(amount)) 353 binary.LittleEndian.PutUint16(s[30:32], limits) 354 return s, 0 355 } 356 357 func (x *xpubAddress) payVoteCommitment() (script []byte, version uint16) { 358 s := []byte{ 359 0: txscript.OP_SSGEN, 360 1: txscript.OP_DUP, 361 2: txscript.OP_HASH160, 362 3: txscript.OP_DATA_20, 363 24: txscript.OP_EQUALVERIFY, 364 25: txscript.OP_CHECKSIG, 365 } 366 copy(s[4:24], x.PubKeyHash()) 367 return s, 0 368 } 369 370 func (x *xpubAddress) payRevokeCommitment() (script []byte, version uint16) { 371 s := []byte{ 372 0: txscript.OP_SSRTX, 373 1: txscript.OP_DUP, 374 2: txscript.OP_HASH160, 375 3: txscript.OP_DATA_20, 376 24: txscript.OP_EQUALVERIFY, 377 25: txscript.OP_CHECKSIG, 378 } 379 copy(s[4:24], x.PubKeyHash()) 380 return s, 0 381 } 382 383 // DefaultGapLimit is the default unused address gap limit defined by BIP0044. 384 const DefaultGapLimit = uint32(20) 385 386 // DefaultAccountGapLimit is the default number of accounts that can be 387 // created in a row without using any of them 388 const DefaultAccountGapLimit = 10 389 390 // gapPolicy defines the policy to use when the BIP0044 address gap limit is 391 // exceeded. 392 type gapPolicy int 393 394 const ( 395 gapPolicyError gapPolicy = iota 396 gapPolicyIgnore 397 gapPolicyWrap 398 ) 399 400 type nextAddressCallOptions struct { 401 policy gapPolicy 402 } 403 404 // NextAddressCallOption defines a call option for the NextAddress family of 405 // wallet methods. 406 type NextAddressCallOption func(*nextAddressCallOptions) 407 408 func withGapPolicy(policy gapPolicy) NextAddressCallOption { 409 return func(o *nextAddressCallOptions) { 410 o.policy = policy 411 } 412 } 413 414 // WithGapPolicyError configures the NextAddress family of methods to error 415 // whenever the gap limit would be exceeded. When this default policy is used, 416 // callers should check errors against the GapLimit error code and let users 417 // specify whether to ignore the gap limit or wrap around to a previously 418 // returned address. 419 func WithGapPolicyError() NextAddressCallOption { 420 return withGapPolicy(gapPolicyError) 421 } 422 423 // WithGapPolicyIgnore configures the NextAddress family of methods to ignore 424 // the gap limit entirely when generating addresses. Exceeding the gap limit 425 // may result in unsynced address child indexes when seed restoring the wallet, 426 // unless the restoring gap limit is increased, as well as breaking automatic 427 // address synchronization of multiple running wallets. 428 // 429 // This is a good policy to use when addresses must never be reused, but be 430 // aware of the issues noted above. 431 func WithGapPolicyIgnore() NextAddressCallOption { 432 return withGapPolicy(gapPolicyIgnore) 433 } 434 435 // WithGapPolicyWrap configures the NextAddress family of methods to wrap around 436 // to a previously returned address instead of erroring or ignoring the gap 437 // limit and returning a new unused address. 438 // 439 // This is a good policy to use for most individual users' wallets where funds 440 // are segmented by accounts and not the addresses that control each output. 441 func WithGapPolicyWrap() NextAddressCallOption { 442 return withGapPolicy(gapPolicyWrap) 443 } 444 445 type addressBuffer struct { 446 branchXpub *hdkeychain.ExtendedKey 447 lastUsed uint32 448 // cursor is added to lastUsed to derive child index 449 // warning: this is not decremented after errors, and therefore may refer 450 // to children beyond the last returned child recorded in the database. 451 cursor uint32 452 lastWatched uint32 453 } 454 455 type bip0044AccountData struct { 456 xpub *hdkeychain.ExtendedKey 457 albExternal addressBuffer 458 albInternal addressBuffer 459 } 460 461 // persistReturnedChildFunc is the function used by nextAddress to update the 462 // database with the child index of a returned address. It is used to abstract 463 // the correct database access required depending on the caller context. 464 // Possible implementations can open a new database write transaction, use an 465 // already open database transaction, or defer the update until a later time 466 // when a write can be performed. 467 type persistReturnedChildFunc func(account, branch, child uint32) error 468 469 // persistReturnedChild returns a synchronous persistReturnedChildFunc which 470 // causes the DB update to occur before nextAddress returns. 471 // 472 // The returned function may be called either inside of a DB update (in which 473 // case maybeDBTX must be the non-nil transaction object) or not in any 474 // transaction at all (in which case it must be nil and the method opens a 475 // transaction). It must never be called while inside a db view as this results 476 // in a deadlock situation. 477 func (w *Wallet) persistReturnedChild(ctx context.Context, maybeDBTX walletdb.ReadWriteTx) persistReturnedChildFunc { 478 return func(account, branch, child uint32) (rerr error) { 479 // Write the returned child index to the database, opening a write 480 // transaction as necessary. 481 if maybeDBTX == nil { 482 var err error 483 defer trace.StartRegion(ctx, "db.Update").End() 484 maybeDBTX, err = w.db.BeginReadWriteTx() 485 if err != nil { 486 return err 487 } 488 region := trace.StartRegion(ctx, "db.ReadWriteTx") 489 defer func() { 490 if rerr == nil { 491 rerr = maybeDBTX.Commit() 492 } else { 493 maybeDBTX.Rollback() 494 } 495 region.End() 496 }() 497 } 498 ns := maybeDBTX.ReadWriteBucket(waddrmgrNamespaceKey) 499 err := w.manager.SyncAccountToAddrIndex(ns, account, child, branch) 500 if err != nil { 501 return err 502 } 503 return w.manager.MarkReturnedChildIndex(maybeDBTX, account, branch, child) 504 } 505 } 506 507 // deferPersistReturnedChild returns a persistReturnedChildFunc that is not 508 // immediately written to the database. Instead, an update function is appended 509 // to the updates slice. This allows all updates to be run under a single 510 // database update later and allows deferred child persistence even when 511 // generating addresess in a view (as long as the update is called after). 512 // 513 // This is preferable to running updates asynchronously using goroutines as it 514 // allows the updates to not be performed if a later error occurs and the child 515 // indexes should not be written. It also allows the updates to be grouped 516 // together in a single atomic transaction. 517 func (w *Wallet) deferPersistReturnedChild(ctx context.Context, updates *[]func(walletdb.ReadWriteTx) error) persistReturnedChildFunc { 518 // These vars are closed-over by the update function and modified by the 519 // returned persist function. 520 var account, branch, child uint32 521 update := func(tx walletdb.ReadWriteTx) error { 522 persist := w.persistReturnedChild(ctx, tx) 523 return persist(account, branch, child) 524 } 525 *updates = append(*updates, update) 526 return func(a, b, c uint32) error { 527 account, branch, child = a, b, c 528 return nil 529 } 530 } 531 532 // nextAddress returns the next address of an account branch. 533 func (w *Wallet) nextAddress(ctx context.Context, op errors.Op, persist persistReturnedChildFunc, 534 accountName string, account, branch uint32, 535 callOpts ...NextAddressCallOption) (stdaddr.Address, error) { 536 537 var opts nextAddressCallOptions // TODO: zero values for now, add to wallet config later. 538 for _, c := range callOpts { 539 c(&opts) 540 } 541 542 defer w.addressBuffersMu.Unlock() 543 w.addressBuffersMu.Lock() 544 ad, ok := w.addressBuffers[account] 545 if !ok { 546 return nil, errors.E(op, errors.NotExist, errors.Errorf("account %d", account)) 547 } 548 549 var alb *addressBuffer 550 switch branch { 551 case udb.ExternalBranch: 552 alb = &ad.albExternal 553 case udb.InternalBranch: 554 alb = &ad.albInternal 555 default: 556 return nil, errors.E(op, errors.Invalid, "branch must be external (0) or internal (1)") 557 } 558 559 for { 560 if ctx.Err() != nil { 561 return nil, ctx.Err() 562 } 563 if alb.cursor >= w.gapLimit { 564 switch opts.policy { 565 case gapPolicyError: 566 return nil, errors.E(op, errors.Policy, 567 "generating next address violates the unused address gap limit policy") 568 569 case gapPolicyIgnore: 570 // Addresses beyond the last used child + gap limit are not 571 // already watched, so this must be done now if the wallet is 572 // connected to a consensus RPC server. Watch addresses in 573 // batches of the gap limit at a time to avoid introducing many 574 // RPCs from repeated new address calls. 575 if alb.cursor%w.gapLimit != 0 { 576 break 577 } 578 n, err := w.NetworkBackend() 579 if err != nil { 580 break 581 } 582 addrs, err := deriveChildAddresses(alb.branchXpub, 583 alb.lastUsed+1+alb.cursor, w.gapLimit, w.chainParams) 584 if err != nil { 585 return nil, errors.E(op, err) 586 } 587 err = n.LoadTxFilter(ctx, false, addrs, nil) 588 if err != nil { 589 return nil, err 590 } 591 592 case gapPolicyWrap: 593 alb.cursor = 0 594 } 595 } 596 597 childIndex := alb.lastUsed + 1 + alb.cursor 598 if childIndex >= hdkeychain.HardenedKeyStart { 599 return nil, errors.E(op, errors.Errorf("account %d branch %d exhausted", 600 account, branch)) 601 } 602 child, err := alb.branchXpub.Child(childIndex) 603 if errors.Is(err, hdkeychain.ErrInvalidChild) { 604 alb.cursor++ 605 continue 606 } 607 if err != nil { 608 return nil, errors.E(op, err) 609 } 610 apkh, err := compat.HD2Address(child, w.chainParams) 611 if err != nil { 612 return nil, errors.E(op, err) 613 } 614 // Write the returned child index to the database. 615 err = persist(account, branch, childIndex) 616 if err != nil { 617 return nil, errors.E(op, err) 618 } 619 alb.cursor++ 620 addr := &xpubAddress{ 621 AddressPubKeyHashEcdsaSecp256k1V0: apkh, 622 xpub: ad.xpub, 623 account: account, 624 accountName: accountName, 625 branch: branch, 626 child: childIndex, 627 } 628 log.Infof("Returning address (account=%v branch=%v child=%v)", account, branch, childIndex) 629 return addr, nil 630 } 631 } 632 633 // signingAddressAtIdx returns accounts's external branch's address at childIdx 634 // and persists that idx in the database. This address is never used on chain, 635 // but is used when signing messages sent to a vspd. 636 func (w *Wallet) signingAddressAtIdx(ctx context.Context, op errors.Op, 637 persist persistReturnedChildFunc, account, childIdx uint32) (stdaddr.Address, error) { 638 addr, err := w.AddressAtIdx(ctx, account, 0, childIdx) 639 if err != nil { 640 return nil, errors.E(op, err) 641 } 642 // Write the returned child index to the database. 643 err = persist(account, 0, childIdx) 644 if err != nil { 645 return nil, errors.E(op, err) 646 } 647 return addr, nil 648 } 649 650 // AddressAtIndex returns the address at branch and childIdx. It does not persist 651 // the returned address in the database. 652 func (w *Wallet) AddressAtIdx(ctx context.Context, account, branch, 653 childIdx uint32) (stdaddr.Address, error) { 654 const op errors.Op = "wallet.AddressAtIdx" 655 defer w.addressBuffersMu.Unlock() 656 w.addressBuffersMu.Lock() 657 ad, ok := w.addressBuffers[account] 658 if !ok { 659 return nil, errors.E(op, errors.NotExist, errors.Errorf("account %d", account)) 660 } 661 662 var alb *addressBuffer 663 switch branch { 664 case 0: 665 alb = &ad.albExternal 666 case 1: 667 alb = &ad.albInternal 668 default: 669 return nil, errors.E(op, errors.Invalid, "branch must be external (0) or internal (1)") 670 } 671 672 if childIdx >= hdkeychain.HardenedKeyStart { 673 return nil, errors.E(op, errors.Errorf("child out of range")) 674 } 675 child, err := alb.branchXpub.Child(childIdx) 676 if err != nil { 677 return nil, errors.E(op, err) 678 } 679 apkh, err := compat.HD2Address(child, w.chainParams) 680 if err != nil { 681 return nil, errors.E(op, err) 682 } 683 addr := &xpubAddress{ 684 AddressPubKeyHashEcdsaSecp256k1V0: apkh, 685 xpub: ad.xpub, 686 account: account, 687 branch: branch, 688 child: childIdx, 689 } 690 log.Infof("Returning address (account=%v branch=%v child=%v)", account, branch, childIdx) 691 return addr, nil 692 } 693 694 func minUint32(a, b uint32) uint32 { 695 if a < b { 696 return a 697 } 698 return b 699 } 700 701 // markUsedAddress updates the database, recording that the previously looked up 702 // managed address has been publicly used. After recording this usage, new 703 // addresses are derived and saved to the db. 704 func (w *Wallet) markUsedAddress(op errors.Op, dbtx walletdb.ReadWriteTx, addr udb.ManagedAddress) error { 705 ns := dbtx.ReadWriteBucket(waddrmgrNamespaceKey) 706 account := addr.Account() 707 err := w.manager.MarkUsed(dbtx, addr.Address()) 708 if err != nil { 709 return errors.E(op, err) 710 } 711 if account == udb.ImportedAddrAccount { 712 return nil 713 } 714 props, err := w.manager.AccountProperties(ns, account) 715 if err != nil { 716 return errors.E(op, err) 717 } 718 lastUsed := props.LastUsedExternalIndex 719 branch := udb.ExternalBranch 720 if addr.Internal() { 721 lastUsed = props.LastUsedInternalIndex 722 branch = udb.InternalBranch 723 } 724 err = w.manager.SyncAccountToAddrIndex(ns, account, 725 minUint32(hdkeychain.HardenedKeyStart-1, lastUsed+w.gapLimit), 726 branch) 727 if err != nil { 728 return errors.E(op, err) 729 } 730 return nil 731 } 732 733 // NewExternalAddress returns an external address. 734 func (w *Wallet) NewExternalAddress(ctx context.Context, account uint32, callOpts ...NextAddressCallOption) (stdaddr.Address, error) { 735 const op errors.Op = "wallet.NewExternalAddress" 736 737 // Imported voting accounts must not be used for normal transactions. 738 if err := w.notVotingAcct(ctx, op, account); err != nil { 739 return nil, err 740 } 741 742 accountName, _ := w.AccountName(ctx, account) 743 return w.nextAddress(ctx, op, w.persistReturnedChild(ctx, nil), 744 accountName, account, udb.ExternalBranch, callOpts...) 745 } 746 747 // NewInternalAddress returns an internal address. 748 func (w *Wallet) NewInternalAddress(ctx context.Context, account uint32, callOpts ...NextAddressCallOption) (stdaddr.Address, error) { 749 const op errors.Op = "wallet.NewInternalAddress" 750 751 // Imported voting accounts must not be used for normal transactions. 752 if err := w.notVotingAcct(ctx, op, account); err != nil { 753 return nil, err 754 } 755 756 accountName, _ := w.AccountName(ctx, account) 757 return w.nextAddress(ctx, op, w.persistReturnedChild(ctx, nil), 758 accountName, account, udb.InternalBranch, callOpts...) 759 } 760 761 // notVotingAcct errors if an account is a special voting type. This account 762 // should not be used to receive funds. 763 func (w *Wallet) notVotingAcct(ctx context.Context, op errors.Op, account uint32) error { 764 var accountType uint8 765 if err := walletdb.View(ctx, w.db, func(dbtx walletdb.ReadTx) error { 766 ns := dbtx.ReadBucket(waddrmgrNamespaceKey) 767 props, err := w.manager.AccountProperties(ns, account) 768 if err != nil { 769 return err 770 } 771 accountType = props.AccountType 772 return nil 773 }); err != nil { 774 return errors.E(op, err) 775 } 776 if udb.IsImportedVoting(accountType) { 777 return errors.E(op, errors.Invalid, "cannot use voting accounts for normal transactions") 778 } 779 return nil 780 } 781 782 func (w *Wallet) newChangeAddress(ctx context.Context, op errors.Op, persist persistReturnedChildFunc, 783 accountName string, account uint32, gap gapPolicy) (stdaddr.Address, error) { 784 785 // Imported voting accounts must not be used for change. 786 if err := w.notVotingAcct(ctx, op, account); err != nil { 787 return nil, err 788 } 789 790 // Addresses can not be generated for the imported account, so as a 791 // workaround, change is sent to the first account. 792 // 793 // Yep, our accounts are broken. 794 if account == udb.ImportedAddrAccount { 795 account = udb.DefaultAccountNum 796 } 797 return w.nextAddress(ctx, op, persist, accountName, account, udb.InternalBranch, withGapPolicy(gap)) 798 } 799 800 // NewChangeAddress returns an internal address. This is identical to 801 // NewInternalAddress but handles the imported account (which can't create 802 // addresses) by using account 0 instead, and always uses the wrapping gap limit 803 // policy. 804 func (w *Wallet) NewChangeAddress(ctx context.Context, account uint32) (stdaddr.Address, error) { 805 const op errors.Op = "wallet.NewChangeAddress" 806 accountName, _ := w.AccountName(ctx, account) 807 return w.newChangeAddress(ctx, op, w.persistReturnedChild(ctx, nil), accountName, account, gapPolicyWrap) 808 } 809 810 // BIP0044BranchNextIndexes returns the next external and internal branch child 811 // indexes of an account. 812 func (w *Wallet) BIP0044BranchNextIndexes(ctx context.Context, account uint32) (extChild, intChild uint32, err error) { 813 const op errors.Op = "wallet.BIP0044BranchNextIndexes" 814 815 defer w.addressBuffersMu.Unlock() 816 w.addressBuffersMu.Lock() 817 818 acctData, ok := w.addressBuffers[account] 819 if !ok { 820 return 0, 0, errors.E(op, errors.NotExist, errors.Errorf("account %v", account)) 821 } 822 extChild = acctData.albExternal.lastUsed + 1 + acctData.albExternal.cursor 823 intChild = acctData.albInternal.lastUsed + 1 + acctData.albInternal.cursor 824 return extChild, intChild, nil 825 } 826 827 // SyncLastReturnedAddress advances the last returned child address for a 828 // BIP00044 account branch. The next returned address for the branch will be 829 // child+1. 830 func (w *Wallet) SyncLastReturnedAddress(ctx context.Context, account, branch, child uint32) error { 831 const op errors.Op = "wallet.ExtendWatchedAddresses" 832 833 var ( 834 branchXpub *hdkeychain.ExtendedKey 835 lastUsed uint32 836 ) 837 err := func() error { 838 defer w.addressBuffersMu.Unlock() 839 w.addressBuffersMu.Lock() 840 841 acctData, ok := w.addressBuffers[account] 842 if !ok { 843 return errors.E(op, errors.NotExist, errors.Errorf("account %v", account)) 844 } 845 var alb *addressBuffer 846 switch branch { 847 case udb.ExternalBranch: 848 alb = &acctData.albInternal 849 case udb.InternalBranch: 850 alb = &acctData.albInternal 851 default: 852 return errors.E(op, errors.Invalid, "branch must be external (0) or internal (1)") 853 } 854 855 branchXpub = alb.branchXpub 856 lastUsed = alb.lastUsed 857 if lastUsed != ^uint32(0) && child > lastUsed { 858 alb.cursor = child - lastUsed 859 } 860 return nil 861 }() 862 if err != nil { 863 return err 864 } 865 866 err = walletdb.Update(ctx, w.db, func(tx walletdb.ReadWriteTx) error { 867 ns := tx.ReadWriteBucket(waddrmgrNamespaceKey) 868 err = w.manager.SyncAccountToAddrIndex(ns, account, child, branch) 869 if err != nil { 870 return err 871 } 872 return w.manager.MarkReturnedChildIndex(tx, account, branch, child) 873 }) 874 if err != nil { 875 return err 876 } 877 878 if n, err := w.NetworkBackend(); err == nil { 879 lastWatched := lastUsed + w.gapLimit 880 if child <= lastWatched { 881 // No need to derive anything more. 882 return nil 883 } 884 additionalAddrs := child - lastWatched 885 addrs, err := deriveChildAddresses(branchXpub, lastUsed+1+w.gapLimit, 886 additionalAddrs, w.chainParams) 887 if err != nil { 888 return errors.E(op, err) 889 } 890 err = n.LoadTxFilter(ctx, false, addrs, nil) 891 if err != nil { 892 return errors.E(op, err) 893 } 894 } 895 896 return nil 897 } 898 899 // ImportedAddresses returns each of the addresses imported into an account. 900 func (w *Wallet) ImportedAddresses(ctx context.Context, account string) (_ []KnownAddress, err error) { 901 const opf = "wallet.ImportedAddresses(%q)" 902 defer func() { 903 if err != nil { 904 op := errors.Opf(opf, account) 905 err = errors.E(op, err) 906 } 907 }() 908 909 if account != "imported" { 910 return nil, errors.E("account does not record imported keys") 911 } 912 913 var addrs []KnownAddress 914 err = walletdb.View(ctx, w.db, func(dbtx walletdb.ReadTx) error { 915 ns := dbtx.ReadBucket(waddrmgrNamespaceKey) 916 f := func(a udb.ManagedAddress) error { 917 ma, err := wrapManagedAddress(a, account, AccountKindImported) 918 if err != nil { 919 return err 920 } 921 addrs = append(addrs, ma) 922 return nil 923 } 924 return w.manager.ForEachAccountAddress(ns, udb.ImportedAddrAccount, f) 925 }) 926 return addrs, err 927 } 928 929 type p2PKHChangeSource struct { 930 persist persistReturnedChildFunc 931 account uint32 932 wallet *Wallet 933 ctx context.Context 934 gapPolicy gapPolicy 935 } 936 937 func (src *p2PKHChangeSource) Script() ([]byte, uint16, error) { 938 const accountName = "" // not returned, so can be faked. 939 changeAddress, err := src.wallet.newChangeAddress(src.ctx, "", src.persist, 940 accountName, src.account, src.gapPolicy) 941 if err != nil { 942 return nil, 0, err 943 } 944 vers, pkScript := changeAddress.PaymentScript() 945 return pkScript, vers, nil 946 } 947 948 func (src *p2PKHChangeSource) ScriptSize() int { 949 return txsizes.P2PKHPkScriptSize 950 } 951 952 // p2PKHTreasuryChangeSource is the change source that shall be used when there 953 // is change on an OP_TADD treasury send. 954 type p2PKHTreasuryChangeSource struct { 955 persist persistReturnedChildFunc 956 account uint32 957 wallet *Wallet 958 ctx context.Context 959 gapPolicy gapPolicy 960 } 961 962 // Script returns the treasury change script and is required for change source 963 // interface. 964 func (src *p2PKHTreasuryChangeSource) Script() ([]byte, uint16, error) { 965 const accountName = "" // not returned, so can be faked. 966 changeAddress, err := src.wallet.newChangeAddress(src.ctx, "", src.persist, 967 accountName, src.account, src.gapPolicy) 968 if err != nil { 969 return nil, 0, err 970 } 971 vers, script := changeAddress.PaymentScript() 972 973 // Prefix script with OP_SSTXCHANGE. 974 s := make([]byte, len(script)+1) 975 s[0] = txscript.OP_SSTXCHANGE 976 copy(s[1:], script) 977 978 return s, vers, nil 979 } 980 981 // ScriptSize returns the treasury change script size. This function is 982 // required for the change source interface. 983 func (src *p2PKHTreasuryChangeSource) ScriptSize() int { 984 return txsizes.P2PKHPkTreasruryScriptSize 985 } 986 987 func deriveChildAddresses(key *hdkeychain.ExtendedKey, startIndex, count uint32, params *chaincfg.Params) ([]stdaddr.Address, error) { 988 addresses := make([]stdaddr.Address, 0, count) 989 for i := uint32(0); i < count; i++ { 990 child, err := key.Child(startIndex + i) 991 if errors.Is(err, hdkeychain.ErrInvalidChild) { 992 continue 993 } 994 if err != nil { 995 return nil, err 996 } 997 addr, err := compat.HD2Address(child, params) 998 if err != nil { 999 return nil, err 1000 } 1001 addresses = append(addresses, addr) 1002 } 1003 return addresses, nil 1004 } 1005 1006 func deriveChildAddress(key *hdkeychain.ExtendedKey, child uint32, params *chaincfg.Params) (stdaddr.Address, error) { 1007 childKey, err := key.Child(child) 1008 if err != nil { 1009 return nil, err 1010 } 1011 return compat.HD2Address(childKey, params) 1012 } 1013 1014 func deriveBranches(acctXpub *hdkeychain.ExtendedKey) (extKey, intKey *hdkeychain.ExtendedKey, err error) { 1015 extKey, err = acctXpub.Child(udb.ExternalBranch) 1016 if err != nil { 1017 return 1018 } 1019 intKey, err = acctXpub.Child(udb.InternalBranch) 1020 return 1021 }