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  }