wallet.go raw

   1  package wallet
   2  
   3  import (
   4  	"bytes"
   5  	"encoding/hex"
   6  	"errors"
   7  	"fmt"
   8  	"sort"
   9  	"strings"
  10  	"sync"
  11  	"time"
  12  
  13  	"github.com/p9c/p9/pkg/qu"
  14  
  15  	"github.com/davecgh/go-spew/spew"
  16  
  17  	"github.com/p9c/p9/pkg/amt"
  18  	"github.com/p9c/p9/pkg/btcaddr"
  19  	"github.com/p9c/p9/pkg/chaincfg"
  20  	"github.com/p9c/p9/pod/config"
  21  
  22  	"github.com/p9c/p9/pkg/blockchain"
  23  	"github.com/p9c/p9/pkg/btcjson"
  24  	"github.com/p9c/p9/pkg/chainclient"
  25  	"github.com/p9c/p9/pkg/chainhash"
  26  	ec "github.com/p9c/p9/pkg/ecc"
  27  	"github.com/p9c/p9/pkg/rpcclient"
  28  	"github.com/p9c/p9/pkg/txauthor"
  29  	"github.com/p9c/p9/pkg/txrules"
  30  	"github.com/p9c/p9/pkg/txscript"
  31  	"github.com/p9c/p9/pkg/util"
  32  	"github.com/p9c/p9/pkg/util/hdkeychain"
  33  	"github.com/p9c/p9/pkg/waddrmgr"
  34  	"github.com/p9c/p9/pkg/walletdb"
  35  	"github.com/p9c/p9/pkg/wire"
  36  	"github.com/p9c/p9/pkg/wtxmgr"
  37  )
  38  
  39  const (
  40  	// InsecurePubPassphrase is the default outer encryption passphrase used for public data (everything but private
  41  	// keys). Using a non-default public passphrase can prevent an attacker without the public passphrase from
  42  	// discovering all past and future wallet addresses if they gain access to the wallet database.
  43  	//
  44  	// NOTE: at time of writing, public encryption only applies to public data in the waddrmgr namespace. Transactions
  45  	// are not yet encrypted.
  46  	InsecurePubPassphrase = ""
  47  	// walletDbWatchingOnlyName = "wowallet.db" recoveryBatchSize is the default number of blocks that will be scanned
  48  	// successively by the recovery manager, in the event that the wallet is started in recovery mode.
  49  	recoveryBatchSize = 2000
  50  )
  51  
  52  // ErrNotSynced describes an error where an operation cannot complete due wallet being out of sync (and perhaps
  53  // currently syncing with) the remote chain server.
  54  var ErrNotSynced = errors.New("wallet is not synchronized with the chain server")
  55  
  56  // Namespace bucket keys.
  57  var (
  58  	waddrmgrNamespaceKey = []byte("waddrmgr")
  59  	wtxmgrNamespaceKey   = []byte("wtxmgr")
  60  )
  61  
  62  // Wallet is a structure containing all the components for a complete wallet. It contains the Armory-style key store
  63  // addresses and keys),
  64  type Wallet struct {
  65  	publicPassphrase []byte
  66  	// Data stores
  67  	db                 walletdb.DB
  68  	Manager            *waddrmgr.Manager
  69  	TxStore            *wtxmgr.Store
  70  	chainClient        chainclient.Interface
  71  	chainClientLock    sync.Mutex
  72  	chainClientSynced  bool
  73  	chainClientSyncMtx sync.Mutex
  74  	lockedOutpoints    map[wire.OutPoint]struct{}
  75  	recoveryWindow     uint32
  76  	// Channels for rescan processing. Requests are added and merged with any waiting requests, before being sent to
  77  	// another goroutine to call the rescan RPC.
  78  	rescanAddJob        chan *RescanJob
  79  	rescanBatch         chan *rescanBatch
  80  	rescanNotifications chan interface{} // From chain server
  81  	rescanProgress      chan *RescanProgressMsg
  82  	rescanFinished      chan *RescanFinishedMsg
  83  	// Channel for transaction creation requests.
  84  	createTxRequests chan createTxRequest
  85  	// Channels for the manager locker.
  86  	unlockRequests     chan unlockRequest
  87  	lockRequests       qu.C
  88  	holdUnlockRequests chan chan heldUnlock
  89  	lockState          chan bool
  90  	changePassphrase   chan changePassphraseRequest
  91  	changePassphrases  chan changePassphrasesRequest
  92  	// Information for reorganization handling.
  93  	// reorganizingLock sync.Mutex
  94  	// reorganizeToHash chainhash.Hash
  95  	// reorganizing     bool
  96  	NtfnServer  *NotificationServer
  97  	PodConfig   *config.Config
  98  	chainParams *chaincfg.Params
  99  	wg          sync.WaitGroup
 100  	started     bool
 101  	quit        qu.C
 102  	quitMu      sync.Mutex
 103  	Update      qu.C
 104  }
 105  
 106  // Start starts the goroutines necessary to manage a wallet.
 107  func (w *Wallet) Start() {
 108  	T.Ln("starting wallet")
 109  	w.quitMu.Lock()
 110  	T.Ln("locked wallet quit mutex")
 111  	select {
 112  	case <-w.quit.Wait():
 113  		T.Ln("waiting for wallet shutdown")
 114  		// Restart the wallet goroutines after shutdown finishes.
 115  		w.WaitForShutdown()
 116  		w.quit = qu.T()
 117  	default:
 118  		if w.started {
 119  			// Ignore when the wallet is still running.
 120  			I.Ln("wallet already started")
 121  			w.quitMu.Unlock()
 122  			return
 123  		}
 124  		w.started = true
 125  	}
 126  	w.quitMu.Unlock()
 127  	T.Ln("wallet quit mutex unlocked")
 128  	w.wg.Add(2)
 129  	go w.txCreator()
 130  	go w.walletLocker()
 131  }
 132  
 133  // SynchronizeRPC associates the wallet with the consensus RPC client, synchronizes the wallet with the latest changes
 134  // to the blockchain, and continuously updates the wallet through RPC notifications.
 135  //
 136  // This method is unstable and will be removed when all syncing logic is moved outside of the wallet package.
 137  func (w *Wallet) SynchronizeRPC(chainClient chainclient.Interface) {
 138  	T.Ln("SynchronizeRPC")
 139  	w.quitMu.Lock()
 140  	select {
 141  	case <-w.quit.Wait():
 142  		w.quitMu.Unlock()
 143  		return
 144  	default:
 145  	}
 146  	w.quitMu.Unlock()
 147  	// TODO: Ignoring the new client when one is already set breaks callers
 148  	//  who are replacing the client, perhaps after a disconnect.
 149  	T.Ln("locking wallet chain client mutex")
 150  	w.chainClientLock.Lock()
 151  	if w.chainClient != nil {
 152  		T.Ln("chain client is nil, unlocking wallet chain client mutex")
 153  		w.chainClientLock.Unlock()
 154  		return
 155  	}
 156  	w.chainClient = chainClient
 157  	// If the chain client is a NeutrinoClient instance, set a birthday so we don't download all the filters as we go.
 158  	switch cc := chainClient.(type) {
 159  	// case *chainclient.NeutrinoClient:
 160  	// 	cc.SetStartTime(w.Manager.Birthday())
 161  	case *chainclient.BitcoindClient:
 162  		cc.SetBirthday(w.Manager.Birthday())
 163  	}
 164  	T.Ln("unlocking wallet chain client mutex")
 165  	w.chainClientLock.Unlock()
 166  	T.Ln("unlocked wallet chain client mutex")
 167  	// TODO: It would be preferable to either run these goroutines separately from the wallet (use wallet mutator
 168  	//  functions to make changes from the RPC client) and not have to stop and restart them each time the client
 169  	//  disconnects and reconnets.
 170  	w.wg.Add(4)
 171  	go w.handleChainNotifications()
 172  	go w.rescanBatchHandler()
 173  	go w.rescanProgressHandler()
 174  	go w.rescanRPCHandler()
 175  }
 176  
 177  // requireChainClient marks that a wallet method can only be completed when the consensus RPC server is set. This
 178  // function and all functions that call it are unstable and will need to be moved when the syncing code is moved out of
 179  // the wallet.
 180  func (w *Wallet) requireChainClient() (chainclient.Interface, error) {
 181  	T.Ln("requireChainClient")
 182  	w.chainClientLock.Lock()
 183  	chainClient := w.chainClient
 184  	w.chainClientLock.Unlock()
 185  	if chainClient == nil {
 186  		T.Ln("chain client is nil")
 187  		return nil, errors.New("wallet->chain RPC is inactive")
 188  	}
 189  	return chainClient, nil
 190  }
 191  
 192  // ChainClient returns the optional consensus RPC client associated with the wallet.
 193  //
 194  // This function is unstable and will be removed once sync logic is moved out of the wallet.
 195  func (w *Wallet) ChainClient() chainclient.Interface {
 196  	T.Ln("wallet acquiring connect to chain RPC")
 197  	w.chainClientLock.Lock()
 198  	T.Ln("chainClientLock locked", w.chainClient == nil)
 199  	chainClient := w.chainClient
 200  	w.chainClientLock.Unlock()
 201  	T.Ln("chainClientLock unlocked")
 202  	return chainClient
 203  }
 204  
 205  // quitChan atomically reads the quit channel.
 206  func (w *Wallet) quitChan() qu.C {
 207  	w.quitMu.Lock()
 208  	c := w.quit
 209  	w.quitMu.Unlock()
 210  	return c
 211  }
 212  
 213  // Stop signals all wallet goroutines to shutdown.
 214  func (w *Wallet) Stop() {
 215  	// T.Ln("w", w, "w.quitMu", w.quitMu)
 216  	w.quitMu.Lock()
 217  	defer w.quitMu.Unlock()
 218  	select {
 219  	case <-w.quit.Wait():
 220  	default:
 221  		w.chainClientLock.Lock()
 222  		if w.chainClient != nil {
 223  			w.chainClient.Stop()
 224  			w.chainClient = nil
 225  		}
 226  		w.chainClientLock.Unlock()
 227  		w.quit.Q()
 228  		// return
 229  	}
 230  }
 231  
 232  // ShuttingDown returns whether the wallet is currently in the process of shutting down or not.
 233  func (w *Wallet) ShuttingDown() bool {
 234  	select {
 235  	case <-w.quitChan().Wait():
 236  		return true
 237  	default:
 238  		return false
 239  	}
 240  }
 241  
 242  // WaitForShutdown blocks until all wallet goroutines have finished executing.
 243  func (w *Wallet) WaitForShutdown() {
 244  	T.Ln("waiting for shutdown")
 245  	w.chainClientLock.Lock()
 246  	T.Ln("locked", w.chainClient)
 247  	if w.chainClient != nil {
 248  		T.Ln("calling WaitForShutdown")
 249  		w.chainClient.WaitForShutdown()
 250  	}
 251  	T.Ln("unlocking")
 252  	w.chainClientLock.Unlock()
 253  	// T.Ln("waiting on waitgroup")
 254  	// w.wg.Wait()
 255  }
 256  
 257  // SynchronizingToNetwork returns whether the wallet is currently synchronizing with the Bitcoin network.
 258  func (w *Wallet) SynchronizingToNetwork() bool {
 259  	// At the moment, RPC is the only synchronization method. In the future, when SPV is added, a separate check will
 260  	// also be needed, or SPV could always be enabled if RPC was not explicitly specified when creating the wallet.
 261  	w.chainClientSyncMtx.Lock()
 262  	syncing := w.chainClient != nil
 263  	w.chainClientSyncMtx.Unlock()
 264  	return syncing
 265  }
 266  
 267  // ChainSynced returns whether the wallet has been attached to a chain server and synced up to the best block on the
 268  // main chain.
 269  func (w *Wallet) ChainSynced() bool {
 270  	w.chainClientSyncMtx.Lock()
 271  	synced := w.chainClientSynced
 272  	w.chainClientSyncMtx.Unlock()
 273  	return synced
 274  }
 275  
 276  // SetChainSynced marks whether the wallet is connected to and currently in sync with the latest block notified by the
 277  // chain server.
 278  //
 279  // NOTE: Due to an API limitation with rpcclient, this may return true after the client disconnected (and is attempting
 280  // a reconnect). This will be unknown until the reconnect notification is received, at which point the wallet can be
 281  // marked out of sync again until after the next rescan completes.
 282  func (w *Wallet) SetChainSynced(synced bool) {
 283  	w.chainClientSyncMtx.Lock()
 284  	w.chainClientSynced = synced
 285  	w.chainClientSyncMtx.Unlock()
 286  }
 287  
 288  // activeData returns the currently-active receiving addresses and all unspent outputs. This is primarily intended to
 289  // provide the parameters for a rescan request.
 290  func (w *Wallet) activeData(dbtx walletdb.ReadTx) (
 291  	addrs []btcaddr.Address, unspent []wtxmgr.Credit, e error,
 292  ) {
 293  	addrmgrNs := dbtx.ReadBucket(waddrmgrNamespaceKey)
 294  	txmgrNs := dbtx.ReadBucket(wtxmgrNamespaceKey)
 295  	if e = w.Manager.ForEachActiveAddress(
 296  		addrmgrNs, func(addr btcaddr.Address) (e error) {
 297  			addrs = append(addrs, addr)
 298  			return nil
 299  		},
 300  	); E.Chk(e) {
 301  		return nil, nil, e
 302  	}
 303  	if unspent, e = w.TxStore.UnspentOutputs(txmgrNs); E.Chk(e) {
 304  	}
 305  	return addrs, unspent, e
 306  }
 307  
 308  // syncWithChain brings the wallet up to date with the current chain server connection. It creates a rescan request and
 309  // blocks until the rescan has finished.
 310  func (w *Wallet) syncWithChain() (e error) {
 311  	T.Ln("syncWithChain")
 312  	var chainClient chainclient.Interface
 313  	chainClient, e = w.requireChainClient()
 314  	if e != nil {
 315  		return e
 316  	}
 317  	// Request notifications for transactions sending to all wallet addresses.
 318  	var (
 319  		addrs   []btcaddr.Address
 320  		unspent []wtxmgr.Credit
 321  	)
 322  	e = walletdb.View(
 323  		w.db, func(dbtx walletdb.ReadTx) (e error) {
 324  			addrs, unspent, e = w.activeData(dbtx)
 325  			return e
 326  		},
 327  	)
 328  	if e != nil {
 329  		W.Ln("error starting sync", e)
 330  		return e
 331  	}
 332  	startHeight := w.Manager.SyncedTo().Height
 333  	// We'll mark this as our first sync if we don't have any unspent outputs as known by the wallet. This will allow us
 334  	// to skip a full rescan at this height, and instead wait for the backend to catch up.
 335  	isInitialSync := len(unspent) == 0
 336  	isRecovery := w.recoveryWindow > 0
 337  	birthday := w.Manager.Birthday()
 338  	// If an initial sync is attempted, we will try and find the block stamp of the first block past our birthday. This
 339  	// will be fed into the rescan to ensure we catch transactions that are sent while performing the initial sync.
 340  	var birthdayStamp *waddrmgr.BlockStamp
 341  	// TODO(jrick): How should this handle a synced height earlier than the chain server best block? When no addresses
 342  	//  have been generated for the wallet, the rescan can be skipped.
 343  	//
 344  	// TODO: This is only correct because activeData above returns all addresses ever created, including those that
 345  	//  don't need to be watched anymore. This code should be updated when this assumption is no longer true, but worst
 346  	//  case would result in an unnecessary rescan.
 347  	if isInitialSync || isRecovery {
 348  		// Find the latest checkpoint's height. This lets us catch up to at least that checkpoint, since we're
 349  		// synchronizing from scratch, and lets us avoid a bunch of costly DB transactions in the case when we're using
 350  		// BDB for the walletdb backend and Neutrino for the chain.Interface backend, and the chain backend starts
 351  		// synchronizing at the same time as the wallet.
 352  		var bestHeight int32
 353  		_, bestHeight, e = chainClient.GetBestBlock()
 354  		if e != nil {
 355  			return e
 356  		}
 357  		T.Ln("bestHeight", bestHeight)
 358  		checkHeight := bestHeight
 359  		if len(w.chainParams.Checkpoints) > 0 {
 360  			checkHeight = w.chainParams.Checkpoints[len(
 361  				w.chainParams.Checkpoints,
 362  			)-1].Height
 363  		}
 364  		logHeight := checkHeight
 365  		if bestHeight > logHeight {
 366  			logHeight = bestHeight
 367  		}
 368  		I.F(
 369  			"catching up block hashes to height %d, this will take a while",
 370  			logHeight,
 371  		)
 372  		// Initialize the first database transaction.
 373  		var tx walletdb.ReadWriteTx
 374  		tx, e = w.db.BeginReadWriteTx()
 375  		if e != nil {
 376  			return e
 377  		}
 378  		ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
 379  		// Only allocate the recoveryMgr if we are actually in recovery mode.
 380  		recoveryMgr := &RecoveryManager{}
 381  		if isRecovery {
 382  			I.Ln(
 383  				"RECOVERY MODE ENABLED -- rescanning for used addresses with recovery_window =",
 384  				w.recoveryWindow,
 385  			)
 386  			// Initialize the recovery manager with a default batch size of 2000.
 387  			I.Ln("initialising recovery manager")
 388  			recoveryMgr = NewRecoveryManager(
 389  				w.recoveryWindow, recoveryBatchSize,
 390  				w.chainParams,
 391  			)
 392  			// In the event that this recovery is being resumed, we will need to repopulate all found addresses from the
 393  			// database. For basic recovery, we will only do so for the default scopes.
 394  			var scopedMgrs map[waddrmgr.KeyScope]*waddrmgr.ScopedKeyManager
 395  			I.Ln("getting scope managers")
 396  			scopedMgrs, e = w.defaultScopeManagers()
 397  			if e != nil {
 398  				return e
 399  			}
 400  			I.Ln("opening read bucket")
 401  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
 402  			var credits []wtxmgr.Credit
 403  			I.Ln("getting unspent outputs")
 404  			credits, e = w.TxStore.UnspentOutputs(txmgrNs)
 405  			if e != nil {
 406  				return e
 407  			}
 408  			I.Ln("resurrecting the dead")
 409  			e = recoveryMgr.Resurrect(ns, scopedMgrs, credits)
 410  			if e != nil {
 411  				return e
 412  			}
 413  			I.Ln("all deads now shambling")
 414  		}
 415  		I.Ln("startHeight", startHeight, "bestHeight", bestHeight)
 416  		for height := startHeight; height <= bestHeight; height++ {
 417  			I.Ln("current height", height)
 418  			var hash *chainhash.Hash
 419  			if hash, e = chainClient.GetBlockHash(int64(height)); E.Chk(e) {
 420  				if e = tx.Rollback(); E.Chk(e) {
 421  				}
 422  				return e
 423  			}
 424  			// // If we're using the Neutrino backend, we can check if it's current or not. For other backends we'll assume
 425  			// // it is current if the best height has reached the last checkpoint.
 426  			// isCurrent := func(bestHeight int32) bool {
 427  			// 	switch c := chainClient.(type) {
 428  			// 	case *chainclient.NeutrinoClient:
 429  			// 		return c.CS.IsCurrent()
 430  			// 	}
 431  			// 	return bestHeight >= checkHeight
 432  			// }
 433  			// If we've found the best height the backend knows about, and the backend is still synchronizing, we'll
 434  			// wait. We can give it a little bit of time to synchronize further before updating the best height based on
 435  			// the backend. Once we see that the backend has advanced, we can catch up to it.
 436  			for height == bestHeight { // && !isCurrent(bestHeight) {
 437  				I.Ln("getting best height from chain")
 438  				if _, bestHeight, e = chainClient.GetBestBlock(); E.Chk(e) {
 439  					if e = tx.Rollback(); E.Chk(e) {
 440  					}
 441  					return e
 442  				} else {
 443  					break
 444  				}
 445  				time.Sleep(time.Second)
 446  			}
 447  			var header *wire.BlockHeader
 448  			header, e = chainClient.GetBlockHeader(hash)
 449  			if e != nil {
 450  				return e
 451  			}
 452  			// Chk to see if this header's timestamp has surpassed our birthday or if we've surpassed one previously.
 453  			timestamp := header.Timestamp
 454  			if timestamp.After(birthday) || birthdayStamp != nil {
 455  				// If this is the first block past our birthday, record the block stamp so that we can use this as the
 456  				// starting point for the rescan. This will ensure we don't miss transactions that are sent to the
 457  				// wallet during an initial sync.
 458  				//
 459  				// NOTE: The birthday persisted by the wallet is two days before the actual wallet birthday, to deal
 460  				// with potentially inaccurate header timestamps.
 461  				if birthdayStamp == nil {
 462  					birthdayStamp = &waddrmgr.BlockStamp{
 463  						Height:    height,
 464  						Hash:      *hash,
 465  						Timestamp: timestamp,
 466  					}
 467  				}
 468  				// If we are in recovery mode and the check passes, we will add this block to our list of blocks to scan
 469  				// for recovered addresses.
 470  				if isRecovery {
 471  					recoveryMgr.AddToBlockBatch(
 472  						hash, height, timestamp,
 473  					)
 474  				}
 475  			}
 476  			e = w.Manager.SetSyncedTo(
 477  				ns, &waddrmgr.BlockStamp{
 478  					Hash:      *hash,
 479  					Height:    height,
 480  					Timestamp: timestamp,
 481  				},
 482  			)
 483  			if e != nil {
 484  				e = tx.Rollback()
 485  				if e != nil {
 486  				}
 487  				return e
 488  			}
 489  			// If we are in recovery mode, attempt a recovery on blocks that have been added to the recovery manager's
 490  			// block batch thus far. If block batch is empty, this will be a NOP.
 491  			if isRecovery && height%recoveryBatchSize == 0 {
 492  				e = w.recoverDefaultScopes(
 493  					chainClient, tx, ns,
 494  					recoveryMgr.BlockBatch(),
 495  					recoveryMgr.State(),
 496  				)
 497  				if e != nil {
 498  					e = tx.Rollback()
 499  					if e != nil {
 500  					}
 501  					return e
 502  				}
 503  				// Clear the batch of all processed blocks.
 504  				recoveryMgr.ResetBlockBatch()
 505  			}
 506  			// Every 10K blocks, commit and start a new database TX.
 507  			if height%10000 == 0 {
 508  				e = tx.Commit()
 509  				if e != nil {
 510  					e = tx.Rollback()
 511  					if e != nil {
 512  					}
 513  					return e
 514  				}
 515  				I.Ln(
 516  					"caught up to height", height,
 517  				)
 518  				tx, e = w.db.BeginReadWriteTx()
 519  				if e != nil {
 520  					return e
 521  				}
 522  				ns = tx.ReadWriteBucket(waddrmgrNamespaceKey)
 523  			}
 524  		}
 525  		// Perform one last recovery attempt for all blocks that were not batched at the default granularity of 2000
 526  		// blocks.
 527  		if isRecovery {
 528  			I.Ln("isRecovery")
 529  			e = w.recoverDefaultScopes(
 530  				chainClient, tx, ns, recoveryMgr.BlockBatch(),
 531  				recoveryMgr.State(),
 532  			)
 533  			if e != nil {
 534  				e = tx.Rollback()
 535  				if e != nil {
 536  				}
 537  				return e
 538  			}
 539  		}
 540  		// Commit (or roll back) the final database transaction.
 541  		if e = tx.Commit(); E.Chk(e) {
 542  			if e = tx.Rollback(); E.Chk(e) {
 543  			}
 544  			return e
 545  		}
 546  		I.Ln("done catching up block hashes")
 547  		// Since we've spent some time catching up block hashes, we might have new addresses waiting for us that were
 548  		// requested during initial sync. Make sure we have those before we request a rescan later on.
 549  		e = walletdb.View(
 550  			w.db, func(dbtx walletdb.ReadTx) (e error) {
 551  				addrs, unspent, e = w.activeData(dbtx)
 552  				return e
 553  			},
 554  		)
 555  		if e != nil {
 556  			return e
 557  		}
 558  	}
 559  	// Compare previously-seen blocks against the chain server. If any of these blocks no longer exist, rollback all of
 560  	// the missing blocks before catching up with the rescan.
 561  	rollback := false
 562  	rollbackStamp := w.Manager.SyncedTo()
 563  	e = walletdb.Update(
 564  		w.db, func(tx walletdb.ReadWriteTx) (e error) {
 565  			addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
 566  			txmgrNs := tx.ReadWriteBucket(wtxmgrNamespaceKey)
 567  			for height := rollbackStamp.Height; true; height-- {
 568  				hash, e := w.Manager.BlockHash(addrmgrNs, height)
 569  				if e != nil {
 570  					return e
 571  				}
 572  				chainHash, e := chainClient.GetBlockHash(int64(height))
 573  				if e != nil {
 574  					return e
 575  				}
 576  				header, e := chainClient.GetBlockHeader(chainHash)
 577  				if e != nil {
 578  					return e
 579  				}
 580  				rollbackStamp.Hash = *chainHash
 581  				rollbackStamp.Height = height
 582  				rollbackStamp.Timestamp = header.Timestamp
 583  				if bytes.Equal(hash[:], chainHash[:]) {
 584  					break
 585  				}
 586  				rollback = true
 587  			}
 588  			if rollback {
 589  				e := w.Manager.SetSyncedTo(addrmgrNs, &rollbackStamp)
 590  				if e != nil {
 591  					return e
 592  				}
 593  				// Rollback unconfirms transactions at and beyond the passed height, so add one to the new synced-to height
 594  				// to prevent unconfirming txs from the synced-to block.
 595  				e = w.TxStore.Rollback(txmgrNs, rollbackStamp.Height+1)
 596  				if e != nil {
 597  					return e
 598  				}
 599  			}
 600  			return nil
 601  		},
 602  	)
 603  	if e != nil {
 604  		return e
 605  	}
 606  	// If a birthday stamp was found during the initial sync and the rollback causes us to revert it, update the
 607  	// birthday stamp so that it points at the new tip.
 608  	if birthdayStamp != nil && rollbackStamp.Height <= birthdayStamp.Height {
 609  		birthdayStamp = &rollbackStamp
 610  	}
 611  	// Request notifications for connected and disconnected blocks.
 612  	//
 613  	// TODO(jrick): Either request this notification only once, or when rpcclient is modified to allow some notification
 614  	//  request to not automatically resent on reconnect, include the notifyblocks request as well. I am leaning towards
 615  	//  allowing off all rpcclient notification re-registrations, in which case the code here should be left as is.
 616  	e = chainClient.NotifyBlocks()
 617  	if e != nil {
 618  		return e
 619  	}
 620  	return w.rescanWithTarget(addrs, unspent, birthdayStamp)
 621  }
 622  
 623  // defaultScopeManagers fetches the ScopedKeyManagers from the wallet using the default set of key scopes.
 624  func (w *Wallet) defaultScopeManagers() (
 625  	map[waddrmgr.KeyScope]*waddrmgr.ScopedKeyManager, error,
 626  ) {
 627  	scopedMgrs := make(map[waddrmgr.KeyScope]*waddrmgr.ScopedKeyManager)
 628  	for _, scope := range waddrmgr.DefaultKeyScopes {
 629  		scopedMgr, e := w.Manager.FetchScopedKeyManager(scope)
 630  		if e != nil {
 631  			return nil, e
 632  		}
 633  		scopedMgrs[scope] = scopedMgr
 634  	}
 635  	return scopedMgrs, nil
 636  }
 637  
 638  // recoverDefaultScopes attempts to recover any addresses belonging to any active scoped key managers known to the
 639  // wallet. Recovery of each scope's default account will be done iteratively against the same batch of blocks.
 640  //
 641  // TODO(conner): parallelize/pipeline/cache intermediate network requests
 642  func (w *Wallet) recoverDefaultScopes(
 643  	chainClient chainclient.Interface,
 644  	tx walletdb.ReadWriteTx,
 645  	ns walletdb.ReadWriteBucket,
 646  	batch []wtxmgr.BlockMeta,
 647  	recoveryState *RecoveryState,
 648  ) (e error) {
 649  	scopedMgrs, e := w.defaultScopeManagers()
 650  	if e != nil {
 651  		return e
 652  	}
 653  	return w.recoverScopedAddresses(
 654  		chainClient, tx, ns, batch, recoveryState, scopedMgrs,
 655  	)
 656  }
 657  
 658  // recoverAccountAddresses scans a range of blocks in attempts to recover any previously used addresses for a particular
 659  // account derivation path. At a high level, the algorithm works as follows:
 660  //
 661  //  1) Ensure internal and external branch horizons are fully expanded.
 662  //
 663  //  2) Filter the entire range of blocks, stopping if a non-zero number of address are contained in a particular block.
 664  //
 665  //  3) Record all internal and external addresses found in the block.
 666  //
 667  //  4) Record any outpoints found in the block that should be watched for spends
 668  //
 669  //  5) Trim the range of blocks up to and including the one reporting the addrs.
 670  //
 671  //  6) Repeat from (1) if there are still more blocks in the range.
 672  func (w *Wallet) recoverScopedAddresses(
 673  	chainClient chainclient.Interface,
 674  	tx walletdb.ReadWriteTx,
 675  	ns walletdb.ReadWriteBucket,
 676  	batch []wtxmgr.BlockMeta,
 677  	recoveryState *RecoveryState,
 678  	scopedMgrs map[waddrmgr.KeyScope]*waddrmgr.ScopedKeyManager,
 679  ) (e error) {
 680  	// If there are no blocks in the batch, we are done.
 681  	if len(batch) == 0 {
 682  		return nil
 683  	}
 684  	I.F(
 685  		"scanning %d blocks for recoverable addresses",
 686  		len(batch),
 687  	)
 688  expandHorizons:
 689  	for scope, scopedMgr := range scopedMgrs {
 690  		scopeState := recoveryState.StateForScope(scope)
 691  		e = expandScopeHorizons(ns, scopedMgr, scopeState)
 692  		if e != nil {
 693  			return e
 694  		}
 695  	}
 696  	// With the internal and external horizons properly expanded, we now construct the filter blocks request. The
 697  	// request includes the range of blocks we intend to scan, in addition to the scope-index -> addr map for all
 698  	// internal and external branches.
 699  	filterReq := newFilterBlocksRequest(batch, scopedMgrs, recoveryState)
 700  	// Initiate the filter blocks request using our chain backend. If an error occurs, we are unable to proceed with the
 701  	// recovery.
 702  	filterResp, e := chainClient.FilterBlocks(filterReq)
 703  	if e != nil {
 704  		return e
 705  	}
 706  	// If the filter response is empty, this signals that the rest of the batch was completed, and no other addresses
 707  	// were discovered. As a result, no further modifications to our recovery state are required and we can proceed to
 708  	// the next batch.
 709  	if filterResp == nil {
 710  		return nil
 711  	}
 712  	// Otherwise, retrieve the block info for the block that detected a non-zero number of address matches.
 713  	block := batch[filterResp.BatchIndex]
 714  	// Log any non-trivial findings of addresses or outpoints.
 715  	logFilterBlocksResp(block, filterResp)
 716  	// Report any external or internal addresses found as a result of the appropriate branch recovery state. Adding
 717  	// indexes above the last-found index of either will result in the horizons being expanded upon the next iteration.
 718  	// Any found addresses are also marked used using the scoped key manager.
 719  	e = extendFoundAddresses(ns, filterResp, scopedMgrs, recoveryState)
 720  	if e != nil {
 721  		return e
 722  	}
 723  	// Update the global set of watched outpoints with any that were found in the block.
 724  	for outPoint, addr := range filterResp.FoundOutPoints {
 725  		recoveryState.AddWatchedOutPoint(&outPoint, addr)
 726  	}
 727  	// Finally, record all of the relevant transactions that were returned in the filter blocks response. This ensures
 728  	// that these transactions and their outputs are tracked when the final rescan is performed.
 729  	for _, txn := range filterResp.RelevantTxns {
 730  		txRecord, e := wtxmgr.NewTxRecordFromMsgTx(
 731  			txn, filterResp.BlockMeta.Time,
 732  		)
 733  		if e != nil {
 734  			return e
 735  		}
 736  		e = w.addRelevantTx(tx, txRecord, &filterResp.BlockMeta)
 737  		if e != nil {
 738  			return e
 739  		}
 740  	}
 741  	// Update the batch to indicate that we've processed all block through the one that returned found addresses.
 742  	batch = batch[filterResp.BatchIndex+1:]
 743  	// If this was not the last block in the batch, we will repeat the filtering process again after expanding our
 744  	// horizons.
 745  	if len(batch) > 0 {
 746  		goto expandHorizons
 747  	}
 748  	return nil
 749  }
 750  
 751  // expandScopeHorizons ensures that the ScopeRecoveryState has an adequately sized look ahead for both its internal and
 752  // external branches. The keys derived here are added to the scope's recovery state, but do not affect the persistent
 753  // state of the wallet. If any invalid child keys are detected, the horizon will be properly extended such that our
 754  // lookahead always includes the proper number of valid child keys.
 755  func expandScopeHorizons(
 756  	ns walletdb.ReadWriteBucket,
 757  	scopedMgr *waddrmgr.ScopedKeyManager,
 758  	scopeState *ScopeRecoveryState,
 759  ) (e error) {
 760  	// Compute the current external horizon and the number of addresses we must derive to ensure we maintain a
 761  	// sufficient recovery window for the external branch.
 762  	exHorizon, exWindow := scopeState.ExternalBranch.ExtendHorizon()
 763  	count, childIndex := uint32(0), exHorizon
 764  	for count < exWindow {
 765  		keyPath := externalKeyPath(childIndex)
 766  		var ep error
 767  		var addr waddrmgr.ManagedAddress
 768  		addr, ep = scopedMgr.DeriveFromKeyPath(ns, keyPath)
 769  		switch {
 770  		case ep == hdkeychain.ErrInvalidChild:
 771  			// Record the existence of an invalid child with the external branch's recovery state. This also increments
 772  			// the branch's horizon so that it accounts for this skipped child index.
 773  			scopeState.ExternalBranch.MarkInvalidChild(childIndex)
 774  			childIndex++
 775  			continue
 776  		case ep != nil:
 777  			return ep
 778  		}
 779  		// Register the newly generated external address and child index with the external branch recovery state.
 780  		scopeState.ExternalBranch.AddAddr(childIndex, addr.Address())
 781  		childIndex++
 782  		count++
 783  	}
 784  	// Compute the current internal horizon and the number of addresses we must derive to ensure we maintain a
 785  	// sufficient recovery window for the internal branch.
 786  	inHorizon, inWindow := scopeState.InternalBranch.ExtendHorizon()
 787  	count, childIndex = 0, inHorizon
 788  	for count < inWindow {
 789  		keyPath := internalKeyPath(childIndex)
 790  		addr, e := scopedMgr.DeriveFromKeyPath(ns, keyPath)
 791  		switch {
 792  		case e == hdkeychain.ErrInvalidChild:
 793  			// Record the existence of an invalid child with the internal branch's recovery state. This also increments
 794  			// the branch's horizon so that it accounts for this skipped child index.
 795  			scopeState.InternalBranch.MarkInvalidChild(childIndex)
 796  			childIndex++
 797  			continue
 798  		case e != nil:
 799  			return e
 800  		}
 801  		// Register the newly generated internal address and child index with the internal branch recovery state.
 802  		scopeState.InternalBranch.AddAddr(childIndex, addr.Address())
 803  		childIndex++
 804  		count++
 805  	}
 806  	return nil
 807  }
 808  
 809  // externalKeyPath returns the relative external derivation path /0/0/index.
 810  func externalKeyPath(index uint32) waddrmgr.DerivationPath {
 811  	return waddrmgr.DerivationPath{
 812  		Account: waddrmgr.DefaultAccountNum,
 813  		Branch:  waddrmgr.ExternalBranch,
 814  		Index:   index,
 815  	}
 816  }
 817  
 818  // internalKeyPath returns the relative internal derivation path /0/1/index.
 819  func internalKeyPath(index uint32) waddrmgr.DerivationPath {
 820  	return waddrmgr.DerivationPath{
 821  		Account: waddrmgr.DefaultAccountNum,
 822  		Branch:  waddrmgr.InternalBranch,
 823  		Index:   index,
 824  	}
 825  }
 826  
 827  // newFilterBlocksRequest constructs FilterBlocksRequests using our current block range, scoped managers, and recovery
 828  // state.
 829  func newFilterBlocksRequest(
 830  	batch []wtxmgr.BlockMeta,
 831  	scopedMgrs map[waddrmgr.KeyScope]*waddrmgr.ScopedKeyManager,
 832  	recoveryState *RecoveryState,
 833  ) *chainclient.FilterBlocksRequest {
 834  	filterReq := &chainclient.FilterBlocksRequest{
 835  		Blocks:           batch,
 836  		ExternalAddrs:    make(map[waddrmgr.ScopedIndex]btcaddr.Address),
 837  		InternalAddrs:    make(map[waddrmgr.ScopedIndex]btcaddr.Address),
 838  		WatchedOutPoints: recoveryState.WatchedOutPoints(),
 839  	}
 840  	// Populate the external and internal addresses by merging the addresses sets belong to all currently tracked
 841  	// scopes.
 842  	for scope := range scopedMgrs {
 843  		scopeState := recoveryState.StateForScope(scope)
 844  		for index, addr := range scopeState.ExternalBranch.Addrs() {
 845  			scopedIndex := waddrmgr.ScopedIndex{
 846  				Scope: scope,
 847  				Index: index,
 848  			}
 849  			filterReq.ExternalAddrs[scopedIndex] = addr
 850  		}
 851  		for index, addr := range scopeState.InternalBranch.Addrs() {
 852  			scopedIndex := waddrmgr.ScopedIndex{
 853  				Scope: scope,
 854  				Index: index,
 855  			}
 856  			filterReq.InternalAddrs[scopedIndex] = addr
 857  		}
 858  	}
 859  	return filterReq
 860  }
 861  
 862  // extendFoundAddresses accepts a filter blocks response that contains addresses found on chain, and advances the state
 863  // of all relevant derivation paths to match the highest found child index for each branch.
 864  func extendFoundAddresses(
 865  	ns walletdb.ReadWriteBucket,
 866  	filterResp *chainclient.FilterBlocksResponse,
 867  	scopedMgrs map[waddrmgr.KeyScope]*waddrmgr.ScopedKeyManager,
 868  	recoveryState *RecoveryState,
 869  ) (e error) {
 870  	// Mark all recovered external addresses as used. This will be done only for scopes that reported a non-zero number
 871  	// of external addresses in this block.
 872  	for scope, indexes := range filterResp.FoundExternalAddrs {
 873  		// First, report all external child indexes found for this scope. This ensures that the external last-found
 874  		// index will be updated to include the maximum child index seen thus far.
 875  		scopeState := recoveryState.StateForScope(scope)
 876  		for index := range indexes {
 877  			scopeState.ExternalBranch.ReportFound(index)
 878  		}
 879  		scopedMgr := scopedMgrs[scope]
 880  		// Now, with all found addresses reported, derive and extend all external addresses up to and including the
 881  		// current last found index for this scope.
 882  		exNextUnfound := scopeState.ExternalBranch.NextUnfound()
 883  		exLastFound := exNextUnfound
 884  		if exLastFound > 0 {
 885  			exLastFound--
 886  		}
 887  		e := scopedMgr.ExtendExternalAddresses(
 888  			ns, waddrmgr.DefaultAccountNum, exLastFound,
 889  		)
 890  		if e != nil {
 891  			return e
 892  		}
 893  		// Finally, with the scope's addresses extended, we mark used the external addresses that were found in the
 894  		// block and belong to this scope.
 895  		for index := range indexes {
 896  			addr := scopeState.ExternalBranch.GetAddr(index)
 897  			e := scopedMgr.MarkUsed(ns, addr)
 898  			if e != nil {
 899  				return e
 900  			}
 901  		}
 902  	}
 903  	// Mark all recovered internal addresses as used. This will be done only for scopes that reported a non-zero number
 904  	// of internal addresses in this block.
 905  	for scope, indexes := range filterResp.FoundInternalAddrs {
 906  		// First, report all internal child indexes found for this scope. This ensures that the internal last-found
 907  		// index will be updated to include the maximum child index seen thus far.
 908  		scopeState := recoveryState.StateForScope(scope)
 909  		for index := range indexes {
 910  			scopeState.InternalBranch.ReportFound(index)
 911  		}
 912  		scopedMgr := scopedMgrs[scope]
 913  		// Now, with all found addresses reported, derive and extend all internal addresses up to and including the
 914  		// current last found index for this scope.
 915  		inNextUnfound := scopeState.InternalBranch.NextUnfound()
 916  		inLastFound := inNextUnfound
 917  		if inLastFound > 0 {
 918  			inLastFound--
 919  		}
 920  		e := scopedMgr.ExtendInternalAddresses(
 921  			ns, waddrmgr.DefaultAccountNum, inLastFound,
 922  		)
 923  		if e != nil {
 924  			return e
 925  		}
 926  		// Finally, with the scope's addresses extended, we mark used the internal addresses that were found in the
 927  		// block and belong to this scope.
 928  		for index := range indexes {
 929  			addr := scopeState.InternalBranch.GetAddr(index)
 930  			e := scopedMgr.MarkUsed(ns, addr)
 931  			if e != nil {
 932  				return e
 933  			}
 934  		}
 935  	}
 936  	return nil
 937  }
 938  
 939  // logFilterBlocksResp provides useful logging information when filtering succeeded in finding relevant transactions.
 940  func logFilterBlocksResp(
 941  	block wtxmgr.BlockMeta,
 942  	resp *chainclient.FilterBlocksResponse,
 943  ) {
 944  	// Log the number of external addresses found in this block.
 945  	var nFoundExternal int
 946  	for _, indexes := range resp.FoundExternalAddrs {
 947  		nFoundExternal += len(indexes)
 948  	}
 949  	if nFoundExternal > 0 {
 950  		T.F(
 951  			"recovered %d external addrs at height=%d hash=%v",
 952  			nFoundExternal, block.Height, block.Hash,
 953  		)
 954  	}
 955  	// Log the number of internal addresses found in this block.
 956  	var nFoundInternal int
 957  	for _, indexes := range resp.FoundInternalAddrs {
 958  		nFoundInternal += len(indexes)
 959  	}
 960  	if nFoundInternal > 0 {
 961  		T.F(
 962  			"recovered %d internal addrs at height=%d hash=%v",
 963  			nFoundInternal, block.Height, block.Hash,
 964  		)
 965  	}
 966  	// Log the number of outpoints found in this block.
 967  	nFoundOutPoints := len(resp.FoundOutPoints)
 968  	if nFoundOutPoints > 0 {
 969  		T.F(
 970  			"found %d spends from watched outpoints at height=%d hash=%v",
 971  			nFoundOutPoints, block.Height, block.Hash,
 972  		)
 973  	}
 974  }
 975  
 976  type (
 977  	createTxRequest struct {
 978  		account     uint32
 979  		outputs     []*wire.TxOut
 980  		minconf     int32
 981  		feeSatPerKB amt.Amount
 982  		resp        chan createTxResponse
 983  	}
 984  	createTxResponse struct {
 985  		tx *txauthor.AuthoredTx
 986  		e  error
 987  	}
 988  )
 989  
 990  // txCreator is responsible for the input selection and creation of transactions. These functions are the responsibility
 991  // of this method (designed to be run as its own goroutine) since input selection must be serialized, or else it is
 992  // possible to create double spends by choosing the same inputs for multiple transactions. Along with input selection,
 993  // this method is also responsible for the signing of transactions, since we don't want to end up in a situation where
 994  // we run out of inputs as multiple transactions are being created. In this situation, it would then be possible for
 995  // both requests, rather than just one, to fail due to not enough available inputs.
 996  func (w *Wallet) txCreator() {
 997  	quit := w.quitChan()
 998  out:
 999  	for {
1000  		select {
1001  		case txr := <-w.createTxRequests:
1002  			var e error
1003  			var h heldUnlock
1004  			h, e = w.holdUnlock()
1005  			if e != nil {
1006  				txr.resp <- createTxResponse{nil, e}
1007  				continue
1008  			}
1009  			var tx *txauthor.AuthoredTx
1010  			tx, e = w.txToOutputs(
1011  				txr.outputs, txr.account,
1012  				txr.minconf, txr.feeSatPerKB,
1013  			)
1014  			h.release()
1015  			txr.resp <- createTxResponse{tx, e}
1016  		case <-quit.Wait():
1017  			break out
1018  		}
1019  	}
1020  	w.wg.Done()
1021  }
1022  
1023  // CreateSimpleTx creates a new signed transaction spending unspent P2PKH outputs with at least minconf confirmations
1024  // spending to any number of address/amount pairs. Change and an appropriate transaction fee are automatically included,
1025  // if necessary. All transaction creation through this function is serialized to prevent the creation of many
1026  // transactions which spend the same outputs.
1027  func (w *Wallet) CreateSimpleTx(
1028  	account uint32, outputs []*wire.TxOut,
1029  	minconf int32, satPerKb amt.Amount,
1030  ) (*txauthor.AuthoredTx, error) {
1031  	req := createTxRequest{
1032  		account:     account,
1033  		outputs:     outputs,
1034  		minconf:     minconf,
1035  		feeSatPerKB: satPerKb,
1036  		resp:        make(chan createTxResponse),
1037  	}
1038  	w.createTxRequests <- req
1039  	resp := <-req.resp
1040  	return resp.tx, resp.e
1041  }
1042  
1043  type (
1044  	unlockRequest struct {
1045  		passphrase []byte
1046  		lockAfter  <-chan time.Time // nil prevents the timeout.
1047  		err        chan error
1048  	}
1049  	changePassphraseRequest struct {
1050  		old, new []byte
1051  		private  bool
1052  		err      chan error
1053  	}
1054  	changePassphrasesRequest struct {
1055  		publicOld, publicNew   []byte
1056  		privateOld, privateNew []byte
1057  		err                    chan error
1058  	}
1059  	// heldUnlock is a tool to prevent the wallet from automatically locking after some timeout before an operation
1060  	// which needed the unlocked wallet has finished. Any acquired heldUnlock *must* be released (preferably with a
1061  	// defer) or the wallet will forever remain unlocked.
1062  	heldUnlock qu.C
1063  )
1064  
1065  // walletLocker manages the locked/unlocked state of a wallet.
1066  func (w *Wallet) walletLocker() {
1067  	var timeout <-chan time.Time
1068  	holdChan := make(heldUnlock)
1069  	quit := w.quitChan()
1070  	// this flips to false once the first unlock has been done, for runasservice opt which shuts down on lock
1071  	// first := true
1072  	var e error
1073  out:
1074  	for {
1075  		select {
1076  		case req := <-w.unlockRequests:
1077  			e = walletdb.View(
1078  				w.db, func(tx walletdb.ReadTx) (e error) {
1079  					addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1080  					return w.Manager.Unlock(addrmgrNs, req.passphrase)
1081  				},
1082  			)
1083  			if e != nil {
1084  				req.err <- e
1085  				continue
1086  			}
1087  			timeout = req.lockAfter
1088  			if timeout == nil {
1089  				I.Ln("the wallet has been unlocked without a time limit")
1090  			} else {
1091  				I.Ln("the wallet has been temporarily unlocked")
1092  			}
1093  			req.err <- nil
1094  			continue
1095  		case req := <-w.changePassphrase:
1096  			e = walletdb.Update(
1097  				w.db, func(tx walletdb.ReadWriteTx) (e error) {
1098  					addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
1099  					return w.Manager.ChangePassphrase(
1100  						addrmgrNs, req.old, req.new, req.private,
1101  						&waddrmgr.DefaultScryptOptions,
1102  					)
1103  				},
1104  			)
1105  			req.err <- e
1106  			continue
1107  		case req := <-w.changePassphrases:
1108  			e = walletdb.Update(
1109  				w.db, func(tx walletdb.ReadWriteTx) (e error) {
1110  					addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
1111  					e = w.Manager.ChangePassphrase(
1112  						addrmgrNs, req.publicOld, req.publicNew,
1113  						false, &waddrmgr.DefaultScryptOptions,
1114  					)
1115  					if e != nil {
1116  						return e
1117  					}
1118  					return w.Manager.ChangePassphrase(
1119  						addrmgrNs, req.privateOld, req.privateNew,
1120  						true, &waddrmgr.DefaultScryptOptions,
1121  					)
1122  				},
1123  			)
1124  			req.err <- e
1125  			continue
1126  		case req := <-w.holdUnlockRequests:
1127  			if w.Manager.IsLocked() {
1128  				close(req)
1129  				continue
1130  			}
1131  			req <- holdChan
1132  			<-holdChan // Block until the lock is released.
1133  			// If, after holding onto the unlocked wallet for some time, the timeout has expired, lock it now instead of
1134  			// hoping it gets unlocked next time the top level select runs.
1135  			select {
1136  			case <-timeout:
1137  				// Let the top level select fallthrough so the wallet is locked.
1138  			default:
1139  				continue
1140  			}
1141  		case w.lockState <- w.Manager.IsLocked():
1142  			continue
1143  		case <-quit.Wait():
1144  			break out
1145  		case <-w.lockRequests.Wait():
1146  			// first = false
1147  		case <-timeout:
1148  			// first = false
1149  		}
1150  		// Select statement fell through by an explicit lock or the timer expiring. Lock the manager here.
1151  		timeout = nil
1152  		e = w.Manager.Lock()
1153  		if e != nil && !waddrmgr.IsError(e, waddrmgr.ErrLocked) {
1154  			E.Ln("could not lock wallet:", e)
1155  		} else {
1156  			I.Ln("the wallet has been locked")
1157  		}
1158  		// if *w.PodConfig.RunAsService && !first {
1159  		// 	// if we are running as a service this means shut down on lock as unlocking happens only at startup
1160  		// 	break out
1161  		// }
1162  	}
1163  	w.wg.Done()
1164  }
1165  
1166  // Unlock unlocks the wallet's address manager and relocks it after timeout has expired. If the wallet is already
1167  // unlocked and the new passphrase is correct, the current timeout is replaced with the new one. The wallet will be
1168  // locked if the passphrase is incorrect or any other error occurs during the unlock.
1169  func (w *Wallet) Unlock(passphrase []byte, lock <-chan time.Time) (e error) {
1170  	eC := make(chan error, 1)
1171  	w.unlockRequests <- unlockRequest{
1172  		passphrase: passphrase,
1173  		lockAfter:  lock,
1174  		err:        eC,
1175  	}
1176  	return <-eC
1177  }
1178  
1179  // Lock locks the wallet's address manager.
1180  func (w *Wallet) Lock() {
1181  	w.lockRequests <- struct{}{}
1182  }
1183  
1184  // Locked returns whether the account manager for a wallet is locked.
1185  func (w *Wallet) Locked() bool {
1186  	return <-w.lockState
1187  }
1188  
1189  // holdUnlock prevents the wallet from being locked. The heldUnlock object *must* be released, or the wallet will
1190  // forever remain unlocked.
1191  //
1192  // TODO: To prevent the above scenario, perhaps closures should be passed to the walletLocker goroutine and disallow
1193  //  callers from explicitly handling the locking mechanism.
1194  func (w *Wallet) holdUnlock() (heldUnlock, error) {
1195  	req := make(chan heldUnlock)
1196  	w.holdUnlockRequests <- req
1197  	hl, ok := <-req
1198  	if !ok {
1199  		// TODO(davec): This should be defined and exported from waddrmgr.
1200  		return nil, waddrmgr.ManagerError{
1201  			ErrorCode:   waddrmgr.ErrLocked,
1202  			Description: "address manager is locked",
1203  		}
1204  	}
1205  	return hl, nil
1206  }
1207  
1208  // release releases the hold on the unlocked-state of the wallet and allows the wallet to be locked again. If a lock
1209  // timeout has already expired, the wallet is locked again as soon as release is called.
1210  func (c heldUnlock) release() {
1211  	c <- struct{}{}
1212  }
1213  
1214  // ChangePrivatePassphrase attempts to change the passphrase for a wallet from old to new. Changing the passphrase is
1215  // synchronized with all other address manager locking and unlocking. The lock state will be the same as it was before
1216  // the password change.
1217  func (w *Wallet) ChangePrivatePassphrase(old, new []byte) (e error) {
1218  	errChan := make(chan error, 1)
1219  	w.changePassphrase <- changePassphraseRequest{
1220  		old:     old,
1221  		new:     new,
1222  		private: true,
1223  		err:     errChan,
1224  	}
1225  	return <-errChan
1226  }
1227  
1228  // ChangePublicPassphrase modifies the public passphrase of the wallet.
1229  func (w *Wallet) ChangePublicPassphrase(old, new []byte) (e error) {
1230  	errChan := make(chan error, 1)
1231  	w.changePassphrase <- changePassphraseRequest{
1232  		old:     old,
1233  		new:     new,
1234  		private: false,
1235  		err:     errChan,
1236  	}
1237  	return <-errChan
1238  }
1239  
1240  // ChangePassphrases modifies the public and private passphrase of the wallet atomically.
1241  func (w *Wallet) ChangePassphrases(
1242  	publicOld, publicNew, privateOld,
1243  	privateNew []byte,
1244  ) (e error) {
1245  	errChan := make(chan error, 1)
1246  	w.changePassphrases <- changePassphrasesRequest{
1247  		publicOld:  publicOld,
1248  		publicNew:  publicNew,
1249  		privateOld: privateOld,
1250  		privateNew: privateNew,
1251  		err:        errChan,
1252  	}
1253  	return <-errChan
1254  }
1255  
1256  // // accountUsed returns whether there are any recorded transactions spending to
1257  // // a given account. It returns true if atleast one address in the account was
1258  // // used and false if no address in the account was used.
1259  // func (w *Wallet) accountUsed(addrmgrNs walletdb.ReadWriteBucket, account uint32) (bool, error) {
1260  // 	var used bool
1261  // 	e := w.Manager.ForEachAccountAddress(addrmgrNs, account,
1262  // 		func(maddr waddrmgr.ManagedAddress) (e error) {
1263  // 			used = maddr.Used(addrmgrNs)
1264  // 			if used {
1265  // 				return waddrmgr.Break
1266  // 			}
1267  // 			return nil
1268  // 		})
1269  // 	if e ==  waddrmgr.Break {
1270  // 		e = nil
1271  // 	}
1272  // 	return used, err
1273  // }
1274  
1275  // AccountAddresses returns the addresses for every created address for an
1276  // account.
1277  func (w *Wallet) AccountAddresses(account uint32) (
1278  	addrs []btcaddr.Address, e error,
1279  ) {
1280  	e = walletdb.View(
1281  		w.db, func(tx walletdb.ReadTx) (e error) {
1282  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1283  			return w.Manager.ForEachAccountAddress(
1284  				addrmgrNs, account, func(maddr waddrmgr.ManagedAddress) (e error) {
1285  					addrs = append(addrs, maddr.Address())
1286  					return nil
1287  				},
1288  			)
1289  		},
1290  	)
1291  	return
1292  }
1293  
1294  // CalculateBalance sums the amounts of all unspent transaction outputs to addresses of a wallet and returns the
1295  // balance.
1296  //
1297  // If confirmations is 0, all UTXOs, even those not present in a block (height -1), will be used to get the balance.
1298  // Otherwise, a UTXO must be in a block. If confirmations is 1 or greater, the balance will be calculated based on how
1299  // many how many blocks include a UTXO.
1300  func (w *Wallet) CalculateBalance(confirms int32) (
1301  	balance amt.Amount, e error,
1302  ) {
1303  	e = walletdb.View(
1304  		w.db, func(tx walletdb.ReadTx) (e error) {
1305  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
1306  			blk := w.Manager.SyncedTo()
1307  			balance, e = w.TxStore.Balance(txmgrNs, confirms, blk.Height)
1308  			return e
1309  		},
1310  	)
1311  	return balance, e
1312  }
1313  
1314  // Balances records total, spendable (by policy), and immature coinbase reward balance amounts.
1315  type Balances struct {
1316  	Total          amt.Amount
1317  	Spendable      amt.Amount
1318  	ImmatureReward amt.Amount
1319  }
1320  
1321  // CalculateAccountBalances sums the amounts of all unspent transaction outputs to the given account of a wallet and
1322  // returns the balance.
1323  //
1324  // This function is much slower than it needs to be since transactions outputs are not indexed by the accounts they
1325  // credit to, and all unspent transaction outputs must be iterated.
1326  func (w *Wallet) CalculateAccountBalances(
1327  	account uint32, confirms int32,
1328  ) (bals Balances, e error) {
1329  	e = walletdb.View(
1330  		w.db, func(tx walletdb.ReadTx) (e error) {
1331  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1332  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
1333  			// Get current block.  The block height used for calculating
1334  			// the number of tx confirmations.
1335  			syncBlock := w.Manager.SyncedTo()
1336  			var unspent []wtxmgr.Credit
1337  			unspent, e = w.TxStore.UnspentOutputs(txmgrNs)
1338  			if e != nil {
1339  				return e
1340  			}
1341  			for i := range unspent {
1342  				output := &unspent[i]
1343  				var outputAcct uint32
1344  				var addrs []btcaddr.Address
1345  				_, addrs, _, e = txscript.ExtractPkScriptAddrs(
1346  					output.PkScript, w.chainParams,
1347  				)
1348  				if e == nil && len(addrs) > 0 {
1349  					_, outputAcct, e = w.Manager.AddrAccount(addrmgrNs, addrs[0])
1350  				}
1351  				if e != nil || outputAcct != account {
1352  					continue
1353  				}
1354  				bals.Total += output.Amount
1355  				if output.FromCoinBase && !confirmed(
1356  					int32(w.chainParams.CoinbaseMaturity),
1357  					output.Height, syncBlock.Height,
1358  				) {
1359  					bals.ImmatureReward += output.Amount
1360  				} else if confirmed(confirms, output.Height, syncBlock.Height) {
1361  					bals.Spendable += output.Amount
1362  				}
1363  			}
1364  			return nil
1365  		},
1366  	)
1367  	return bals, e
1368  }
1369  
1370  // CurrentAddress gets the most recently requested Bitcoin payment address from a wallet for a particular key-chain
1371  // scope. If the address has already been used (there is at least one transaction spending to it in the blockchain or
1372  // pod mempool), the next chained address is returned.
1373  func (w *Wallet) CurrentAddress(
1374  	account uint32, scope waddrmgr.KeyScope,
1375  ) (btcaddr.Address, error) {
1376  	chainClient, e := w.requireChainClient()
1377  	if e != nil {
1378  		return nil, e
1379  	}
1380  	manager, e := w.Manager.FetchScopedKeyManager(scope)
1381  	if e != nil {
1382  		return nil, e
1383  	}
1384  	var (
1385  		addr  btcaddr.Address
1386  		props *waddrmgr.AccountProperties
1387  	)
1388  	e = walletdb.Update(
1389  		w.db, func(tx walletdb.ReadWriteTx) (e error) {
1390  			addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
1391  			maddr, e := manager.LastExternalAddress(addrmgrNs, account)
1392  			if e != nil {
1393  				// If no address exists yet, create the first external address.
1394  				if waddrmgr.IsError(e, waddrmgr.ErrAddressNotFound) {
1395  					addr, props, e = w.newAddress(
1396  						addrmgrNs, account, scope,
1397  					)
1398  				}
1399  				return e
1400  			}
1401  			// Get next chained address if the last one has already been used.
1402  			if maddr.Used(addrmgrNs) {
1403  				addr, props, e = w.newAddress(
1404  					addrmgrNs, account, scope,
1405  				)
1406  				return e
1407  			}
1408  			addr = maddr.Address()
1409  			return nil
1410  		},
1411  	)
1412  	if e != nil {
1413  		return nil, e
1414  	}
1415  	// If the props have been initially, then we had to create a new address to satisfy the query. Notify the rpc server
1416  	// about the new address.
1417  	if props != nil {
1418  		e = chainClient.NotifyReceived([]btcaddr.Address{addr})
1419  		if e != nil {
1420  			return nil, e
1421  		}
1422  		w.NtfnServer.notifyAccountProperties(props)
1423  	}
1424  	return addr, nil
1425  }
1426  
1427  // PubKeyForAddress looks up the associated public key for a P2PKH address.
1428  func (w *Wallet) PubKeyForAddress(a btcaddr.Address) (
1429  	pubKey *ec.PublicKey, e error,
1430  ) {
1431  	e = walletdb.View(
1432  		w.db, func(tx walletdb.ReadTx) (e error) {
1433  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1434  			managedAddr, e := w.Manager.Address(addrmgrNs, a)
1435  			if e != nil {
1436  				return e
1437  			}
1438  			managedPubKeyAddr, ok := managedAddr.(waddrmgr.ManagedPubKeyAddress)
1439  			if !ok {
1440  				return errors.New("address does not have an associated public key")
1441  			}
1442  			pubKey = managedPubKeyAddr.PubKey()
1443  			return nil
1444  		},
1445  	)
1446  	return
1447  }
1448  
1449  // PrivKeyForAddress looks up the associated private key for a P2PKH or P2PK address.
1450  func (w *Wallet) PrivKeyForAddress(a btcaddr.Address) (
1451  	privKey *ec.PrivateKey, e error,
1452  ) {
1453  	e = walletdb.View(
1454  		w.db, func(tx walletdb.ReadTx) (e error) {
1455  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1456  			managedAddr, e := w.Manager.Address(addrmgrNs, a)
1457  			if e != nil {
1458  				return e
1459  			}
1460  			managedPubKeyAddr, ok := managedAddr.(waddrmgr.ManagedPubKeyAddress)
1461  			if !ok {
1462  				return errors.New("address does not have an associated private key")
1463  			}
1464  			privKey, e = managedPubKeyAddr.PrivKey()
1465  			return e
1466  		},
1467  	)
1468  	return privKey, e
1469  }
1470  
1471  // HaveAddress returns whether the wallet is the owner of the address a.
1472  func (w *Wallet) HaveAddress(a btcaddr.Address) (b bool, e error) {
1473  	e = walletdb.View(
1474  		w.db, func(tx walletdb.ReadTx) (e error) {
1475  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1476  			_, e = w.Manager.Address(addrmgrNs, a)
1477  			return e
1478  		},
1479  	)
1480  	if e == nil {
1481  		return true, nil
1482  	}
1483  	if waddrmgr.IsError(e, waddrmgr.ErrAddressNotFound) {
1484  		return false, nil
1485  	}
1486  	return false, e
1487  }
1488  
1489  // AccountOfAddress finds the account that an address is associated with.
1490  func (w *Wallet) AccountOfAddress(a btcaddr.Address) (account uint32, e error) {
1491  	e = walletdb.View(
1492  		w.db, func(tx walletdb.ReadTx) (e error) {
1493  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1494  			_, account, e = w.Manager.AddrAccount(addrmgrNs, a)
1495  			return e
1496  		},
1497  	)
1498  	return account, e
1499  }
1500  
1501  // AddressInfo returns detailed information regarding a wallet address.
1502  func (w *Wallet) AddressInfo(a btcaddr.Address) (
1503  	waddrmgr.ManagedAddress, error,
1504  ) {
1505  	var managedAddress waddrmgr.ManagedAddress
1506  	e := walletdb.View(
1507  		w.db, func(tx walletdb.ReadTx) (e error) {
1508  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1509  			managedAddress, e = w.Manager.Address(addrmgrNs, a)
1510  			return e
1511  		},
1512  	)
1513  	return managedAddress, e
1514  }
1515  
1516  // AccountNumber returns the account number for an account name under a particular key scope.
1517  func (w *Wallet) AccountNumber(
1518  	scope waddrmgr.KeyScope, accountName string,
1519  ) (account uint32, e error) {
1520  	var manager *waddrmgr.ScopedKeyManager
1521  	manager, e = w.Manager.FetchScopedKeyManager(scope)
1522  	if e != nil {
1523  		return 0, e
1524  	}
1525  	e = walletdb.View(
1526  		w.db, func(tx walletdb.ReadTx) (e error) {
1527  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1528  			account, e = manager.LookupAccount(addrmgrNs, accountName)
1529  			return e
1530  		},
1531  	)
1532  	return account, e
1533  }
1534  
1535  // AccountName returns the name of an account.
1536  func (w *Wallet) AccountName(
1537  	scope waddrmgr.KeyScope, accountNumber uint32,
1538  ) (string, error) {
1539  	manager, e := w.Manager.FetchScopedKeyManager(scope)
1540  	if e != nil {
1541  		return "", e
1542  	}
1543  	var accountName string
1544  	e = walletdb.View(
1545  		w.db, func(tx walletdb.ReadTx) (e error) {
1546  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1547  			accountName, e = manager.AccountName(addrmgrNs, accountNumber)
1548  			return e
1549  		},
1550  	)
1551  	return accountName, e
1552  }
1553  
1554  // AccountProperties returns the properties of an account, including address indexes and name. It first fetches the
1555  // desynced information from the address manager, then updates the indexes based on the address pools.
1556  func (w *Wallet) AccountProperties(
1557  	scope waddrmgr.KeyScope, acct uint32,
1558  ) (*waddrmgr.AccountProperties, error) {
1559  	manager, e := w.Manager.FetchScopedKeyManager(scope)
1560  	if e != nil {
1561  		return nil, e
1562  	}
1563  	var props *waddrmgr.AccountProperties
1564  	e = walletdb.View(
1565  		w.db, func(tx walletdb.ReadTx) (e error) {
1566  			waddrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1567  			props, e = manager.AccountProperties(waddrmgrNs, acct)
1568  			return e
1569  		},
1570  	)
1571  	return props, e
1572  }
1573  
1574  // RenameAccount sets the name for an account number to newName.
1575  func (w *Wallet) RenameAccount(
1576  	scope waddrmgr.KeyScope, account uint32, newName string,
1577  ) (e error) {
1578  	manager, e := w.Manager.FetchScopedKeyManager(scope)
1579  	if e != nil {
1580  		return e
1581  	}
1582  	var props *waddrmgr.AccountProperties
1583  	e = walletdb.Update(
1584  		w.db, func(tx walletdb.ReadWriteTx) (e error) {
1585  			addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
1586  			e = manager.RenameAccount(addrmgrNs, account, newName)
1587  			if e != nil {
1588  				return e
1589  			}
1590  			props, e = manager.AccountProperties(addrmgrNs, account)
1591  			return e
1592  		},
1593  	)
1594  	if e == nil {
1595  		w.NtfnServer.notifyAccountProperties(props)
1596  	}
1597  	return e
1598  }
1599  
1600  // const maxEmptyAccounts = 100
1601  
1602  // NextAccount creates the next account and returns its account number. The name must be unique to the account. In order
1603  // to support automatic seed restoring, new accounts may not be created when all of the previous 100 accounts have no
1604  // transaction history (this is a deviation from the BIP0044 spec, which allows no unused account gaps).
1605  func (w *Wallet) NextAccount(scope waddrmgr.KeyScope, name string) (
1606  	uint32, error,
1607  ) {
1608  	manager, e := w.Manager.FetchScopedKeyManager(scope)
1609  	if e != nil {
1610  		return 0, e
1611  	}
1612  	var (
1613  		account uint32
1614  		props   *waddrmgr.AccountProperties
1615  	)
1616  	e = walletdb.Update(
1617  		w.db, func(tx walletdb.ReadWriteTx) (e error) {
1618  			addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
1619  			account, e = manager.NewAccount(addrmgrNs, name)
1620  			if e != nil {
1621  				return e
1622  			}
1623  			props, e = manager.AccountProperties(addrmgrNs, account)
1624  			return e
1625  		},
1626  	)
1627  	if e != nil {
1628  		E.Ln(
1629  			"cannot fetch new account properties for notification after"+
1630  				" account creation:", e,
1631  		)
1632  	}
1633  	w.NtfnServer.notifyAccountProperties(props)
1634  	return account, e
1635  }
1636  
1637  // CreditCategory describes the type of wallet transaction output. The category of "sent transactions" (debits) is
1638  // always "send", and is not expressed by this type.
1639  //
1640  // TODO: This is a requirement of the RPC server and should be moved.
1641  type CreditCategory byte
1642  
1643  // These constants define the possible credit categories.
1644  const (
1645  	CreditReceive CreditCategory = iota
1646  	CreditGenerate
1647  	CreditImmature
1648  )
1649  
1650  // String returns the category as a string. This string may be used as the JSON string for categories as part of
1651  // listtransactions and gettransaction RPC responses.
1652  func (c CreditCategory) String() string {
1653  	switch c {
1654  	case CreditReceive:
1655  		return "receive"
1656  	case CreditGenerate:
1657  		return "generate"
1658  	case CreditImmature:
1659  		return "immature"
1660  	default:
1661  		return "unknown"
1662  	}
1663  }
1664  
1665  // RecvCategory returns the category of received credit outputs from a transaction record. The passed block chain height
1666  // is used to distinguish immature from mature coinbase outputs.
1667  //
1668  // TODO: This is intended for use by the RPC server and should be moved out of this package at a later time.
1669  func RecvCategory(
1670  	details *wtxmgr.TxDetails, syncHeight int32, net *chaincfg.Params,
1671  ) CreditCategory {
1672  	if blockchain.IsCoinBaseTx(&details.MsgTx) {
1673  		if confirmed(
1674  			int32(net.CoinbaseMaturity), details.Block.Height,
1675  			syncHeight,
1676  		) {
1677  			return CreditGenerate
1678  		}
1679  		return CreditImmature
1680  	}
1681  	return CreditReceive
1682  }
1683  
1684  // listTransactions creates a object that may be marshalled to a response result for a listtransactions RPC.
1685  //
1686  // TODO: This should be moved to the legacyrpc package.
1687  func listTransactions(
1688  	tx walletdb.ReadTx, details *wtxmgr.TxDetails, addrMgr *waddrmgr.Manager,
1689  	syncHeight int32, net *chaincfg.Params,
1690  ) []btcjson.ListTransactionsResult {
1691  	addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
1692  	var (
1693  		blockHashStr  string
1694  		blockTime     int64
1695  		confirmations int64
1696  	)
1697  	if details.Block.Height != -1 {
1698  		blockHashStr = details.Block.Hash.String()
1699  		blockTime = details.Block.Time.Unix()
1700  		confirmations = int64(confirms(details.Block.Height, syncHeight))
1701  	}
1702  	results := []btcjson.ListTransactionsResult{}
1703  	txHashStr := details.Hash.String()
1704  	received := details.Received.Unix()
1705  	generated := blockchain.IsCoinBaseTx(&details.MsgTx)
1706  	recvCat := RecvCategory(details, syncHeight, net).String()
1707  	send := len(details.Debits) != 0
1708  	// Fee can only be determined if every input is a debit.
1709  	var feeF64 float64
1710  	if len(details.Debits) == len(details.MsgTx.TxIn) {
1711  		var debitTotal amt.Amount
1712  		for _, deb := range details.Debits {
1713  			debitTotal += deb.Amount
1714  		}
1715  		var outputTotal amt.Amount
1716  		for _, output := range details.MsgTx.TxOut {
1717  			outputTotal += amt.Amount(output.Value)
1718  		}
1719  		// Note: The actual fee is debitTotal - outputTotal. However, this RPC reports negative numbers for fees, so the
1720  		// inverse is calculated.
1721  		feeF64 = (outputTotal - debitTotal).ToDUO()
1722  	}
1723  outputs:
1724  	for i, output := range details.MsgTx.TxOut {
1725  		// Determine if this output is a credit, and if so, determine its spentness.
1726  		var isCredit bool
1727  		var spentCredit bool
1728  		for _, cred := range details.Credits {
1729  			if cred.Index == uint32(i) {
1730  				// Change outputs are ignored.
1731  				if cred.Change {
1732  					continue outputs
1733  				}
1734  				isCredit = true
1735  				spentCredit = cred.Spent
1736  				break
1737  			}
1738  		}
1739  		var address string
1740  		var accountName string
1741  		_, addrs, _, _ := txscript.ExtractPkScriptAddrs(output.PkScript, net)
1742  		if len(addrs) == 1 {
1743  			addr := addrs[0]
1744  			address = addr.EncodeAddress()
1745  			mgr, account, e := addrMgr.AddrAccount(addrmgrNs, addrs[0])
1746  			if e == nil {
1747  				accountName, e = mgr.AccountName(addrmgrNs, account)
1748  				if e != nil {
1749  					accountName = ""
1750  				}
1751  			}
1752  		}
1753  		amountF64 := amt.Amount(output.Value).ToDUO()
1754  		blockIndex := int64(details.Block.Height)
1755  		result := btcjson.ListTransactionsResult{
1756  			// Fields left zeroed:
1757  			//   InvolvesWatchOnly
1758  			//   BlockIndex
1759  			//
1760  			// Fields set below:
1761  			//   Account (only for non-"send" categories)
1762  			//   Category
1763  			//   Amount
1764  			//   Fee
1765  			Address:         address,
1766  			Vout:            uint32(i),
1767  			Confirmations:   confirmations,
1768  			Generated:       generated,
1769  			BlockHash:       blockHashStr,
1770  			BlockIndex:      blockIndex,
1771  			BlockTime:       blockTime,
1772  			TxID:            txHashStr,
1773  			WalletConflicts: []string{},
1774  			Time:            received,
1775  			TimeReceived:    received,
1776  		}
1777  		// Add a received/generated/immature result if this is a credit. If the output was spent, create a second result
1778  		// under the send category with the inverse of the output amount. It is therefore possible that a single output
1779  		// may be included in the results set zero, one, or two times.
1780  		//
1781  		// Since credits are not saved for outputs that are not controlled by this wallet, all non-credits from
1782  		// transactions with debits are grouped under the send category.
1783  		if send || spentCredit {
1784  			result.Category = "send"
1785  			result.Amount = -amountF64
1786  			result.Fee = feeF64
1787  			results = append(results, result)
1788  		}
1789  		if isCredit {
1790  			result.Account = accountName
1791  			result.Category = recvCat
1792  			result.Amount = amountF64
1793  			result.Fee = 0
1794  			results = append(results, result)
1795  		}
1796  	}
1797  	return results
1798  }
1799  
1800  // ListSinceBlock returns a slice of objects with details about transactions since the given block. If the block is -1
1801  // then all transactions are included. This is intended to be used for listsinceblock RPC replies.
1802  func (w *Wallet) ListSinceBlock(start, end, syncHeight int32) (
1803  	txList []btcjson.ListTransactionsResult, e error,
1804  ) {
1805  	txList = []btcjson.ListTransactionsResult{}
1806  	e = walletdb.View(
1807  		w.db, func(tx walletdb.ReadTx) (e error) {
1808  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
1809  			rangeFn := func(details []wtxmgr.TxDetails) (bool, error) {
1810  				for _, detail := range details {
1811  					jsonResults := listTransactions(
1812  						tx, &detail,
1813  						w.Manager, syncHeight, w.chainParams,
1814  					)
1815  					txList = append(txList, jsonResults...)
1816  				}
1817  				return false, nil
1818  			}
1819  			return w.TxStore.RangeTransactions(txmgrNs, start, end, rangeFn)
1820  		},
1821  	)
1822  	return
1823  }
1824  
1825  // ListTransactions returns a slice of objects with details about a recorded
1826  // transaction. This is intended to be used for listtransactions RPC replies.
1827  func (w *Wallet) ListTransactions(from, count int) (
1828  	txList []btcjson.ListTransactionsResult, e error,
1829  ) {
1830  	// txList := []btcjson.ListTransactionsResult{}
1831  	// T.Ln("ListTransactions", from, count)
1832  	if e = walletdb.View(
1833  		w.db, func(tx walletdb.ReadTx) (e error) {
1834  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
1835  			// Get current block. The block height used for calculating the number of tx
1836  			// confirmations.
1837  			syncBlock := w.Manager.SyncedTo()
1838  			D.Ln("synced to", syncBlock)
1839  			// Need to skip the first from transactions, and after those, only include the
1840  			// next count transactions.
1841  			skipped := 0
1842  			n := 0
1843  			rangeFn := func(details []wtxmgr.TxDetails) (bool, error) {
1844  				// Iterate over transactions at this height in reverse order. This does nothing
1845  				// for unmined transactions, which are unsorted, but it will process mined
1846  				// transactions in the reverse order they were marked mined.
1847  				for i := len(details) - 1; i >= 0; i-- {
1848  					if from > skipped {
1849  						skipped++
1850  						continue
1851  					}
1852  					n++
1853  					if n > count {
1854  						return true, nil
1855  					}
1856  					jsonResults := listTransactions(
1857  						tx, &details[i],
1858  						w.Manager, syncBlock.Height, w.chainParams,
1859  					)
1860  					txList = append(txList, jsonResults...)
1861  					if len(jsonResults) > 0 {
1862  						n++
1863  					}
1864  				}
1865  				return false, nil
1866  			}
1867  			// Return newer results first by starting at mempool height and working down to
1868  			// the genesis block.
1869  			return w.TxStore.RangeTransactions(txmgrNs, -1, 0, rangeFn)
1870  		},
1871  	); E.Chk(e) {
1872  	}
1873  	return
1874  }
1875  
1876  // ListAddressTransactions returns a slice of objects with details about recorded transactions to or from any address
1877  // belonging to a set. This is intended to be used for listaddresstransactions RPC replies.
1878  func (w *Wallet) ListAddressTransactions(pkHashes map[string]struct{}) (
1879  	txList []btcjson.ListTransactionsResult,
1880  	e error,
1881  ) {
1882  	txList = []btcjson.ListTransactionsResult{}
1883  	e = walletdb.View(
1884  		w.db, func(tx walletdb.ReadTx) (e error) {
1885  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
1886  			// Get current block. The block height used for calculating the number of tx confirmations.
1887  			syncBlock := w.Manager.SyncedTo()
1888  			rangeFn := func(details []wtxmgr.TxDetails) (bool, error) {
1889  			loopDetails:
1890  				for i := range details {
1891  					detail := &details[i]
1892  					for _, cred := range detail.Credits {
1893  						pkScript := detail.MsgTx.TxOut[cred.Index].PkScript
1894  						var addrs []btcaddr.Address
1895  						_, addrs, _, e = txscript.ExtractPkScriptAddrs(
1896  							pkScript, w.chainParams,
1897  						)
1898  						if e != nil || len(addrs) != 1 {
1899  							continue
1900  						}
1901  						apkh, ok := addrs[0].(*btcaddr.PubKeyHash)
1902  						if !ok {
1903  							continue
1904  						}
1905  						_, ok = pkHashes[string(apkh.ScriptAddress())]
1906  						if !ok {
1907  							continue
1908  						}
1909  						jsonResults := listTransactions(
1910  							tx, detail,
1911  							w.Manager, syncBlock.Height, w.chainParams,
1912  						)
1913  						// if e != nil  {
1914  						// 	return false, err
1915  						// }
1916  						txList = append(txList, jsonResults...)
1917  						continue loopDetails
1918  					}
1919  				}
1920  				return false, nil
1921  			}
1922  			return w.TxStore.RangeTransactions(txmgrNs, 0, -1, rangeFn)
1923  		},
1924  	)
1925  	return txList, e
1926  }
1927  
1928  // ListAllTransactions returns a slice of objects with details about a recorded transaction. This is intended to be used
1929  // for listalltransactions RPC replies.
1930  func (w *Wallet) ListAllTransactions() (
1931  	txList []btcjson.ListTransactionsResult, e error,
1932  ) {
1933  	txList = []btcjson.ListTransactionsResult{}
1934  	e = walletdb.View(
1935  		w.db, func(tx walletdb.ReadTx) (e error) {
1936  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
1937  			// Get current block. The block height used for calculating the number of tx confirmations.
1938  			syncBlock := w.Manager.SyncedTo()
1939  			rangeFn := func(details []wtxmgr.TxDetails) (bool, error) {
1940  				// Iterate over transactions at this height in reverse order. This does nothing for unmined transactions,
1941  				// which are unsorted, but it will process mined transactions in the reverse order they were marked mined.
1942  				for i := len(details) - 1; i >= 0; i-- {
1943  					jsonResults := listTransactions(
1944  						tx, &details[i], w.Manager,
1945  						syncBlock.Height, w.chainParams,
1946  					)
1947  					txList = append(txList, jsonResults...)
1948  				}
1949  				return false, nil
1950  			}
1951  			// Return newer results first by starting at mempool height and working down to the genesis block.
1952  			return w.TxStore.RangeTransactions(txmgrNs, -1, 0, rangeFn)
1953  		},
1954  	)
1955  	return txList, e
1956  }
1957  
1958  // BlockIdentifier identifies a block by either a height or a hash.
1959  type BlockIdentifier struct {
1960  	height int32
1961  	hash   *chainhash.Hash
1962  }
1963  
1964  // NewBlockIdentifierFromHeight constructs a BlockIdentifier for a block height.
1965  func NewBlockIdentifierFromHeight(height int32) *BlockIdentifier {
1966  	return &BlockIdentifier{height: height}
1967  }
1968  
1969  // NewBlockIdentifierFromHash constructs a BlockIdentifier for a block hash.
1970  func NewBlockIdentifierFromHash(hash *chainhash.Hash) *BlockIdentifier {
1971  	return &BlockIdentifier{hash: hash}
1972  }
1973  
1974  // GetTransactionsResult is the result of the wallet's GetTransactions method. See GetTransactions for more details.
1975  type GetTransactionsResult struct {
1976  	MinedTransactions   []Block
1977  	UnminedTransactions []TransactionSummary
1978  }
1979  
1980  // GetTransactions returns transaction results between a starting and ending block. BlockC in the block range may be
1981  // specified by either a height or a hash.
1982  //
1983  // Because this is a possibly lengthy operation, a cancel channel is provided to cancel the task. If this channel
1984  // unblocks, the results created thus far will be returned.
1985  //
1986  // Transaction results are organized by blocks in ascending order and unmined transactions in an unspecified order.
1987  // Mined transactions are saved in a Block structure which records properties about the block.
1988  func (w *Wallet) GetTransactions(
1989  	startBlock, endBlock *BlockIdentifier, cancel qu.C,
1990  ) (
1991  	res *GetTransactionsResult,
1992  	e error,
1993  ) {
1994  	var start, end int32 = 0, -1
1995  	w.chainClientLock.Lock()
1996  	chainClient := w.chainClient
1997  	w.chainClientLock.Unlock()
1998  	// TODO: Fetching block heights by their hashes is inherently racy because not all block headers are saved but when
1999  	//  they are for SPV the db can be queried directly without this.
2000  	var startResp, endResp rpcclient.FutureGetBlockVerboseResult
2001  	if startBlock != nil {
2002  		if startBlock.hash == nil {
2003  			start = startBlock.height
2004  		} else {
2005  			if chainClient == nil {
2006  				return nil, errors.New("no chain server client")
2007  			}
2008  			switch client := chainClient.(type) {
2009  			case *chainclient.RPCClient:
2010  				startResp = client.GetBlockVerboseTxAsync(startBlock.hash)
2011  			case *chainclient.BitcoindClient:
2012  				start, e = client.GetBlockHeight(startBlock.hash)
2013  				if e != nil {
2014  					return nil, e
2015  				}
2016  				// case *chainclient.NeutrinoClient:
2017  				// 	start, e = client.GetBlockHeight(startBlock.hash)
2018  				// 	if e != nil {
2019  				// 		return nil, e
2020  				// 	}
2021  			}
2022  		}
2023  	}
2024  	if endBlock != nil {
2025  		if endBlock.hash == nil {
2026  			end = endBlock.height
2027  		} else {
2028  			if chainClient == nil {
2029  				return nil, errors.New("no chain server client")
2030  			}
2031  			switch client := chainClient.(type) {
2032  			case *chainclient.RPCClient:
2033  				endResp = client.GetBlockVerboseTxAsync(endBlock.hash)
2034  				// case *chainclient.NeutrinoClient:
2035  				// 	end, e = client.GetBlockHeight(endBlock.hash)
2036  				// 	if e != nil {
2037  				// 		return nil, e
2038  				// 	}
2039  			}
2040  		}
2041  	}
2042  	var resp *btcjson.GetBlockVerboseResult
2043  	if startResp != nil {
2044  		resp, e = startResp.Receive()
2045  		if e != nil {
2046  			return nil, e
2047  		}
2048  		start = int32(resp.Height)
2049  	}
2050  	if endResp != nil {
2051  		resp, e = endResp.Receive()
2052  		if e != nil {
2053  			return nil, e
2054  		}
2055  		end = int32(resp.Height)
2056  	}
2057  	res = &GetTransactionsResult{}
2058  	e = walletdb.View(
2059  		w.db, func(dbtx walletdb.ReadTx) (e error) {
2060  			txmgrNs := dbtx.ReadBucket(wtxmgrNamespaceKey)
2061  			rangeFn := func(details []wtxmgr.TxDetails) (bool, error) {
2062  				// TODO: probably should make RangeTransactions not reuse the
2063  				// details backing array memory.
2064  				dets := make([]wtxmgr.TxDetails, len(details))
2065  				copy(dets, details)
2066  				details = dets
2067  				txs := make([]TransactionSummary, 0, len(details))
2068  				for i := range details {
2069  					txs = append(txs, makeTxSummary(dbtx, w, &details[i]))
2070  				}
2071  				if details[0].Block.Height != -1 {
2072  					blockHash := details[0].Block.Hash
2073  					res.MinedTransactions = append(
2074  						res.MinedTransactions, Block{
2075  							Hash:         &blockHash,
2076  							Height:       details[0].Block.Height,
2077  							Timestamp:    details[0].Block.Time.Unix(),
2078  							Transactions: txs,
2079  						},
2080  					)
2081  				} else {
2082  					res.UnminedTransactions = txs
2083  				}
2084  				select {
2085  				case <-cancel.Wait():
2086  					return true, nil
2087  				default:
2088  					return false, nil
2089  				}
2090  			}
2091  			return w.TxStore.RangeTransactions(txmgrNs, start, end, rangeFn)
2092  		},
2093  	)
2094  	return res, e
2095  }
2096  
2097  // AccountResult is a single account result for the AccountsResult type.
2098  type AccountResult struct {
2099  	waddrmgr.AccountProperties
2100  	TotalBalance amt.Amount
2101  }
2102  
2103  // AccountsResult is the result of the wallet's Accounts method. See that method for more details.
2104  type AccountsResult struct {
2105  	Accounts           []AccountResult
2106  	CurrentBlockHash   *chainhash.Hash
2107  	CurrentBlockHeight int32
2108  }
2109  
2110  // Accounts returns the current names, numbers, and total balances of all accounts in the wallet restricted to a
2111  // particular key scope. The current chain tip is included in the result for atomicity reasons.
2112  //
2113  // TODO(jrick): Is the chain tip really needed, since only the total balances are included?
2114  func (w *Wallet) Accounts(scope waddrmgr.KeyScope) (*AccountsResult, error) {
2115  	manager, e := w.Manager.FetchScopedKeyManager(scope)
2116  	if e != nil {
2117  		return nil, e
2118  	}
2119  	var (
2120  		accounts        []AccountResult
2121  		syncBlockHash   *chainhash.Hash
2122  		syncBlockHeight int32
2123  	)
2124  	e = walletdb.View(
2125  		w.db, func(tx walletdb.ReadTx) (e error) {
2126  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
2127  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
2128  			syncBlock := w.Manager.SyncedTo()
2129  			syncBlockHash = &syncBlock.Hash
2130  			syncBlockHeight = syncBlock.Height
2131  			unspent, e := w.TxStore.UnspentOutputs(txmgrNs)
2132  			if e != nil {
2133  				return e
2134  			}
2135  			e = manager.ForEachAccount(
2136  				addrmgrNs, func(acct uint32) (e error) {
2137  					props, e := manager.AccountProperties(addrmgrNs, acct)
2138  					if e != nil {
2139  						return e
2140  					}
2141  					accounts = append(
2142  						accounts, AccountResult{
2143  							AccountProperties: *props,
2144  							// TotalBalance set below
2145  						},
2146  					)
2147  					return nil
2148  				},
2149  			)
2150  			if e != nil {
2151  				return e
2152  			}
2153  			m := make(map[uint32]*amt.Amount)
2154  			for i := range accounts {
2155  				a := &accounts[i]
2156  				m[a.AccountNumber] = &a.TotalBalance
2157  			}
2158  			for i := range unspent {
2159  				output := unspent[i]
2160  				var outputAcct uint32
2161  				var addrs []btcaddr.Address
2162  				_, addrs, _, e = txscript.ExtractPkScriptAddrs(output.PkScript, w.chainParams)
2163  				if e == nil && len(addrs) > 0 {
2164  					_, outputAcct, e = w.Manager.AddrAccount(addrmgrNs, addrs[0])
2165  				}
2166  				if e == nil {
2167  					amt, ok := m[outputAcct]
2168  					if ok {
2169  						*amt += output.Amount
2170  					}
2171  				}
2172  			}
2173  			return nil
2174  		},
2175  	)
2176  	return &AccountsResult{
2177  			Accounts:           accounts,
2178  			CurrentBlockHash:   syncBlockHash,
2179  			CurrentBlockHeight: syncBlockHeight,
2180  		},
2181  		e
2182  }
2183  
2184  // AccountBalanceResult is a single result for the Wallet.AccountBalances method.
2185  type AccountBalanceResult struct {
2186  	AccountNumber  uint32
2187  	AccountName    string
2188  	AccountBalance amt.Amount
2189  }
2190  
2191  // AccountBalances returns all accounts in the wallet and their balances. Balances are determined by excluding
2192  // transactions that have not met requiredConfs confirmations.
2193  func (w *Wallet) AccountBalances(
2194  	scope waddrmgr.KeyScope,
2195  	requiredConfs int32,
2196  ) ([]AccountBalanceResult, error) {
2197  	manager, e := w.Manager.FetchScopedKeyManager(scope)
2198  	if e != nil {
2199  		return nil, e
2200  	}
2201  	var results []AccountBalanceResult
2202  	e = walletdb.View(
2203  		w.db, func(tx walletdb.ReadTx) (e error) {
2204  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
2205  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
2206  			syncBlock := w.Manager.SyncedTo()
2207  			// Fill out all account info except for the balances.
2208  			lastAcct, e := manager.LastAccount(addrmgrNs)
2209  			if e != nil {
2210  				return e
2211  			}
2212  			results = make([]AccountBalanceResult, lastAcct+2)
2213  			for i := range results[:len(results)-1] {
2214  				var accountName string
2215  				accountName, e = manager.AccountName(addrmgrNs, uint32(i))
2216  				if e != nil {
2217  					return e
2218  				}
2219  				results[i].AccountNumber = uint32(i)
2220  				results[i].AccountName = accountName
2221  			}
2222  			results[len(results)-1].AccountNumber = waddrmgr.ImportedAddrAccount
2223  			results[len(results)-1].AccountName = waddrmgr.ImportedAddrAccountName
2224  			// Fetch all unspent outputs, and iterate over them tallying each account's balance where the output script pays
2225  			// to an account address and the required number of confirmations is met.
2226  			unspentOutputs, e := w.TxStore.UnspentOutputs(txmgrNs)
2227  			if e != nil {
2228  				return e
2229  			}
2230  			for i := range unspentOutputs {
2231  				output := &unspentOutputs[i]
2232  				if !confirmed(requiredConfs, output.Height, syncBlock.Height) {
2233  					continue
2234  				}
2235  				if output.FromCoinBase && !confirmed(
2236  					int32(w.ChainParams().CoinbaseMaturity),
2237  					output.Height, syncBlock.Height,
2238  				) {
2239  					continue
2240  				}
2241  				var addrs []btcaddr.Address
2242  				_, addrs, _, e = txscript.ExtractPkScriptAddrs(output.PkScript, w.chainParams)
2243  				if e != nil || len(addrs) == 0 {
2244  					continue
2245  				}
2246  				outputAcct, e := manager.AddrAccount(addrmgrNs, addrs[0])
2247  				if e != nil {
2248  					continue
2249  				}
2250  				switch {
2251  				case outputAcct == waddrmgr.ImportedAddrAccount:
2252  					results[len(results)-1].AccountBalance += output.Amount
2253  				case outputAcct > lastAcct:
2254  					return errors.New(
2255  						"waddrmgr.Manager.AddrAccount returned account " +
2256  							"beyond recorded last account",
2257  					)
2258  				default:
2259  					results[outputAcct].AccountBalance += output.Amount
2260  				}
2261  			}
2262  			return nil
2263  		},
2264  	)
2265  	return results, e
2266  }
2267  
2268  // creditSlice satisfies the sort.Interface interface to provide sorting transaction credits from oldest to newest.
2269  // Credits with the same receive time and mined in the same block are not guaranteed to be sorted by the order they
2270  // appear in the block. Credits from the same transaction are sorted by output index.
2271  type creditSlice []wtxmgr.Credit
2272  
2273  func (s creditSlice) Len() int {
2274  	return len(s)
2275  }
2276  func (s creditSlice) Less(i, j int) bool {
2277  	switch {
2278  	// If both credits are from the same tx, txsort by output index.
2279  	case s[i].OutPoint.Hash == s[j].OutPoint.Hash:
2280  		return s[i].OutPoint.Index < s[j].OutPoint.Index
2281  	// If both transactions are unmined, txsort by their received date.
2282  	case s[i].Height == -1 && s[j].Height == -1:
2283  		return s[i].Received.Before(s[j].Received)
2284  	// Unmined (newer) txs always come last.
2285  	case s[i].Height == -1:
2286  		return false
2287  	case s[j].Height == -1:
2288  		return true
2289  	// If both txs are mined in different blocks, txsort by block height.
2290  	default:
2291  		return s[i].Height < s[j].Height
2292  	}
2293  }
2294  func (s creditSlice) Swap(i, j int) {
2295  	s[i], s[j] = s[j], s[i]
2296  }
2297  
2298  // ListUnspent returns a slice of objects representing the unspent wallet transactions fitting the given criteria. The
2299  // confirmations will be more than minconf, less than maxconf and if addresses is populated only the addresses contained
2300  // within it will be considered. If we know nothing about a transaction an empty array will be returned.
2301  func (w *Wallet) ListUnspent(
2302  	minconf, maxconf int32,
2303  	addresses map[string]struct{},
2304  ) (results []*btcjson.ListUnspentResult, e error) {
2305  	e = walletdb.View(
2306  		w.db, func(tx walletdb.ReadTx) (e error) {
2307  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
2308  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
2309  			syncBlock := w.Manager.SyncedTo()
2310  			filter := len(addresses) != 0
2311  			unspent, e := w.TxStore.UnspentOutputs(txmgrNs)
2312  			if e != nil {
2313  				return e
2314  			}
2315  			sort.Sort(sort.Reverse(creditSlice(unspent)))
2316  			defaultAccountName := "default"
2317  			results = make([]*btcjson.ListUnspentResult, 0, len(unspent))
2318  			for i := range unspent {
2319  				output := unspent[i]
2320  				// Outputs with fewer confirmations than the minimum or more confs than the maximum are excluded.
2321  				confs := confirms(output.Height, syncBlock.Height)
2322  				if confs < minconf || confs > maxconf {
2323  					continue
2324  				}
2325  				// Only mature coinbase outputs are included.
2326  				if output.FromCoinBase {
2327  					target := int32(w.ChainParams().CoinbaseMaturity)
2328  					if !confirmed(target, output.Height, syncBlock.Height) {
2329  						continue
2330  					}
2331  				}
2332  				// Exclude locked outputs from the result set.
2333  				if w.LockedOutpoint(output.OutPoint) {
2334  					continue
2335  				}
2336  				// Lookup the associated account for the output. Use the default account name in case there is no associated
2337  				// account for some reason, although this should never happen.
2338  				//
2339  				// This will be unnecessary once transactions and outputs are grouped under the associated account in the
2340  				// db.
2341  				acctName := defaultAccountName
2342  				var sc txscript.ScriptClass
2343  				var addrs []btcaddr.Address
2344  				sc, addrs, _, e = txscript.ExtractPkScriptAddrs(
2345  					output.PkScript, w.chainParams,
2346  				)
2347  				if e != nil {
2348  					continue
2349  				}
2350  				if len(addrs) > 0 {
2351  					smgr, acct, e := w.Manager.AddrAccount(addrmgrNs, addrs[0])
2352  					if e == nil {
2353  						s, e := smgr.AccountName(addrmgrNs, acct)
2354  						if e == nil {
2355  							acctName = s
2356  						}
2357  					}
2358  				}
2359  				if filter {
2360  					for _, addr := range addrs {
2361  						_, ok := addresses[addr.EncodeAddress()]
2362  						if ok {
2363  							goto include
2364  						}
2365  					}
2366  					continue
2367  				}
2368  			include:
2369  				// At the moment watch-only addresses are not supported, so all recorded outputs that are not multisig are
2370  				// "spendable". Multisig outputs are only "spendable" if all keys are controlled by this wallet.
2371  				//
2372  				// TODO: Each case will need updates when watch-only addrs is added. For P2PK, P2PKH, and P2SH, the address
2373  				//  must be looked up and not be watching-only. For multisig, all pubkeys must belong to the manager with the
2374  				//  associated private key (currently it only checks whether the pubkey exists, since the private key is
2375  				//  required at the moment).
2376  				var spendable bool
2377  			scSwitch:
2378  				switch sc {
2379  				case txscript.PubKeyHashTy:
2380  					spendable = true
2381  				case txscript.PubKeyTy:
2382  					spendable = true
2383  				// case txscript.WitnessV0ScriptHashTy:
2384  				// 	spendable = true
2385  				// case txscript.WitnessV0PubKeyHashTy:
2386  				// 	spendable = true
2387  				case txscript.MultiSigTy:
2388  					for _, a := range addrs {
2389  						_, e := w.Manager.Address(addrmgrNs, a)
2390  						if e == nil {
2391  							continue
2392  						}
2393  						if waddrmgr.IsError(e, waddrmgr.ErrAddressNotFound) {
2394  							break scSwitch
2395  						}
2396  						return e
2397  					}
2398  					spendable = true
2399  				}
2400  				result := &btcjson.ListUnspentResult{
2401  					TxID:          output.OutPoint.Hash.String(),
2402  					Vout:          output.OutPoint.Index,
2403  					Account:       acctName,
2404  					ScriptPubKey:  hex.EncodeToString(output.PkScript),
2405  					Amount:        output.Amount.ToDUO(),
2406  					Confirmations: int64(confs),
2407  					Spendable:     spendable,
2408  				}
2409  				// BUG: this should be a JSON array so that all addresses can be included, or removed (and the caller
2410  				// extracts addresses from the pkScript).
2411  				if len(addrs) > 0 {
2412  					result.Address = addrs[0].EncodeAddress()
2413  				}
2414  				results = append(results, result)
2415  			}
2416  			return nil
2417  		},
2418  	)
2419  	return results, e
2420  }
2421  
2422  // DumpPrivKeys returns the WIF-encoded private keys for all addresses with private keys in a wallet.
2423  func (w *Wallet) DumpPrivKeys() (privkeys []string, e error) {
2424  	e = walletdb.View(
2425  		w.db, func(tx walletdb.ReadTx) (e error) {
2426  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
2427  			// Iterate over each active address, appending the private key to privkeys.
2428  			return w.Manager.ForEachActiveAddress(
2429  				addrmgrNs, func(addr btcaddr.Address) (e error) {
2430  					var ma waddrmgr.ManagedAddress
2431  					ma, e = w.Manager.Address(addrmgrNs, addr)
2432  					if e != nil {
2433  						return e
2434  					}
2435  					// Only those addresses with keys needed.
2436  					pka, ok := ma.(waddrmgr.ManagedPubKeyAddress)
2437  					if !ok {
2438  						return nil
2439  					}
2440  					var wif *util.WIF
2441  					wif, e = pka.ExportPrivKey()
2442  					if e != nil {
2443  						// It would be nice to zero out the array here. However, since strings in go are immutable, and we have
2444  						// no control over the caller I don't think we can. :(
2445  						return e
2446  					}
2447  					privkeys = append(privkeys, wif.String())
2448  					return nil
2449  				},
2450  			)
2451  		},
2452  	)
2453  	return privkeys, e
2454  }
2455  
2456  // DumpWIFPrivateKey returns the WIF encoded private key for a single wallet address.
2457  func (w *Wallet) DumpWIFPrivateKey(addr btcaddr.Address) (
2458  	address string, e error,
2459  ) {
2460  	var maddr waddrmgr.ManagedAddress
2461  	e = walletdb.View(
2462  		w.db, func(tx walletdb.ReadTx) (e error) {
2463  			waddrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
2464  			// Get private key from wallet if it exists.
2465  			maddr, e = w.Manager.Address(waddrmgrNs, addr)
2466  			return e
2467  		},
2468  	)
2469  	if e != nil {
2470  		return "", e
2471  	}
2472  	pka, ok := maddr.(waddrmgr.ManagedPubKeyAddress)
2473  	if !ok {
2474  		return "", fmt.Errorf("address %s is not a key type", addr)
2475  	}
2476  	wif, e := pka.ExportPrivKey()
2477  	if e != nil {
2478  		return "", e
2479  	}
2480  	return wif.String(), nil
2481  }
2482  
2483  // ImportPrivateKey imports a private key to the wallet and writes the new wallet to disk.
2484  func (w *Wallet) ImportPrivateKey(
2485  	scope waddrmgr.KeyScope, wif *util.WIF,
2486  	bs *waddrmgr.BlockStamp, rescan bool,
2487  ) (string, error) {
2488  	manager, e := w.Manager.FetchScopedKeyManager(scope)
2489  	if e != nil {
2490  		return "", e
2491  	}
2492  	// The starting block for the key is the genesis block unless otherwise specified.
2493  	var newBirthday time.Time
2494  	if bs == nil {
2495  		bs = &waddrmgr.BlockStamp{
2496  			Hash:   *w.chainParams.GenesisHash,
2497  			Height: 0,
2498  		}
2499  	} else {
2500  		// Only update the new birthday time from default value if we actually have timestamp info in the header.
2501  		var header *wire.BlockHeader
2502  		header, e = w.chainClient.GetBlockHeader(&bs.Hash)
2503  		if e == nil {
2504  			newBirthday = header.Timestamp
2505  		}
2506  	}
2507  	// Attempt to import private key into wallet.
2508  	var addr btcaddr.Address
2509  	var props *waddrmgr.AccountProperties
2510  	e = walletdb.Update(
2511  		w.db, func(tx walletdb.ReadWriteTx) (e error) {
2512  			addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
2513  			maddr, e := manager.ImportPrivateKey(addrmgrNs, wif, bs)
2514  			if e != nil {
2515  				return e
2516  			}
2517  			addr = maddr.Address()
2518  			props, e = manager.AccountProperties(
2519  				addrmgrNs, waddrmgr.ImportedAddrAccount,
2520  			)
2521  			if e != nil {
2522  				return e
2523  			}
2524  			return w.Manager.SetBirthday(addrmgrNs, newBirthday)
2525  		},
2526  	)
2527  	if e != nil {
2528  		return "", e
2529  	}
2530  	// Rescan blockchain for transactions with txout scripts paying to the imported address.
2531  	if rescan {
2532  		job := &RescanJob{
2533  			Addrs:      []btcaddr.Address{addr},
2534  			OutPoints:  nil,
2535  			BlockStamp: *bs,
2536  		}
2537  		// Submit rescan job and log when the import has completed. Do not block on finishing the rescan. The rescan
2538  		// success or failure is logged elsewhere, and the channel is not required to be read, so discard the return
2539  		// value.
2540  		_ = w.SubmitRescan(job)
2541  	} else {
2542  		e := w.chainClient.NotifyReceived([]btcaddr.Address{addr})
2543  		if e != nil {
2544  			return "", fmt.Errorf(
2545  				"failed to subscribe for address ntfns for "+
2546  					"address %s: %s", addr.EncodeAddress(), e,
2547  			)
2548  		}
2549  	}
2550  	addrStr := addr.EncodeAddress()
2551  	I.Ln("imported payment address", addrStr)
2552  	w.NtfnServer.notifyAccountProperties(props)
2553  	// Return the payment address string of the imported private key.
2554  	return addrStr, nil
2555  }
2556  
2557  // LockedOutpoint returns whether an outpoint has been marked as locked and should not be used as an input for created
2558  // transactions.
2559  func (w *Wallet) LockedOutpoint(op wire.OutPoint) bool {
2560  	_, locked := w.lockedOutpoints[op]
2561  	return locked
2562  }
2563  
2564  // LockOutpoint marks an outpoint as locked, that is, it should not be used as an input for newly created transactions.
2565  func (w *Wallet) LockOutpoint(op wire.OutPoint) {
2566  	w.lockedOutpoints[op] = struct{}{}
2567  }
2568  
2569  // UnlockOutpoint marks an outpoint as unlocked, that is, it may be used as an input for newly created transactions.
2570  func (w *Wallet) UnlockOutpoint(op wire.OutPoint) {
2571  	delete(w.lockedOutpoints, op)
2572  }
2573  
2574  // ResetLockedOutpoints resets the set of locked outpoints so all may be used as inputs for new transactions.
2575  func (w *Wallet) ResetLockedOutpoints() {
2576  	w.lockedOutpoints = map[wire.OutPoint]struct{}{}
2577  }
2578  
2579  // LockedOutpoints returns a slice of currently locked outpoints. This is intended to be used by marshaling the result
2580  // as a JSON array for listlockunspent RPC results.
2581  func (w *Wallet) LockedOutpoints() []btcjson.TransactionInput {
2582  	locked := make([]btcjson.TransactionInput, len(w.lockedOutpoints))
2583  	i := 0
2584  	for op := range w.lockedOutpoints {
2585  		locked[i] = btcjson.TransactionInput{
2586  			Txid: op.Hash.String(),
2587  			Vout: op.Index,
2588  		}
2589  		i++
2590  	}
2591  	return locked
2592  }
2593  
2594  // resendUnminedTxs iterates through all transactions that spend from wallet credits that are not known to have been
2595  // mined into a block, and attempts to send each to the chain server for relay.
2596  func (w *Wallet) resendUnminedTxs() {
2597  	chainClient, e := w.requireChainClient()
2598  	if e != nil {
2599  		E.Ln("no chain server available to resend unmined transactions", e)
2600  		return
2601  	}
2602  	var txs []*wire.MsgTx
2603  	e = walletdb.View(
2604  		w.db, func(tx walletdb.ReadTx) (e error) {
2605  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
2606  			txs, e = w.TxStore.UnminedTxs(txmgrNs)
2607  			return e
2608  		},
2609  	)
2610  	if e != nil {
2611  		E.Ln("cannot load unmined transactions for resending:", e)
2612  		return
2613  	}
2614  	for _, tx := range txs {
2615  		resp, e := chainClient.SendRawTransaction(tx, false)
2616  		if e != nil {
2617  			D.F(
2618  				"could not resend transaction %v: %v %s",
2619  				tx.TxHash(), e,
2620  			)
2621  			// We'll only stop broadcasting transactions if we detect that the output has already been fully spent, is
2622  			// an orphan, or is conflicting with another transaction.
2623  			//
2624  			// TODO(roasbeef): SendRawTransaction needs to return concrete error types, no need for string matching
2625  			switch {
2626  			// The following are errors returned from pod's mempool.
2627  			case strings.Contains(e.Error(), "spent"):
2628  			case strings.Contains(e.Error(), "orphan"):
2629  			case strings.Contains(e.Error(), "conflict"):
2630  			case strings.Contains(e.Error(), "already exists"):
2631  			case strings.Contains(e.Error(), "negative"):
2632  			// The following errors are returned from bitcoind's
2633  			// mempool.
2634  			case strings.Contains(e.Error(), "Missing inputs"):
2635  			case strings.Contains(e.Error(), "already in block chain"):
2636  			case strings.Contains(e.Error(), "fee not met"):
2637  			default:
2638  				continue
2639  			}
2640  			// As the transaction was rejected, we'll attempt to remove the unmined transaction all together. Otherwise,
2641  			// we'll keep attempting to rebroadcast this, and we may be computing our balance incorrectly if this tx
2642  			// credits or debits to us.
2643  			tt := tx
2644  			e := walletdb.Update(
2645  				w.db, func(dbTx walletdb.ReadWriteTx) (e error) {
2646  					txmgrNs := dbTx.ReadWriteBucket(wtxmgrNamespaceKey)
2647  					txRec, e := wtxmgr.NewTxRecordFromMsgTx(
2648  						tt, time.Now(),
2649  					)
2650  					if e != nil {
2651  						return e
2652  					}
2653  					return w.TxStore.RemoveUnminedTx(txmgrNs, txRec)
2654  				},
2655  			)
2656  			if e != nil {
2657  				W.F(
2658  					"unable to remove conflicting tx %v: %v %s", tt.TxHash(),
2659  					e,
2660  				)
2661  				continue
2662  			}
2663  			I.C(
2664  				func() string {
2665  					return "removed conflicting tx:" + spew.Sdump(tt) + " "
2666  				},
2667  			)
2668  			continue
2669  		}
2670  		D.Ln("resent unmined transaction", resp)
2671  	}
2672  }
2673  
2674  // SortedActivePaymentAddresses returns a slice of all active payment addresses in a wallet.
2675  func (w *Wallet) SortedActivePaymentAddresses() ([]string, error) {
2676  	var addrStrs []string
2677  	e := walletdb.View(
2678  		w.db, func(tx walletdb.ReadTx) (e error) {
2679  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
2680  			return w.Manager.ForEachActiveAddress(
2681  				addrmgrNs, func(addr btcaddr.Address) (e error) {
2682  					addrStrs = append(addrStrs, addr.EncodeAddress())
2683  					return nil
2684  				},
2685  			)
2686  		},
2687  	)
2688  	if e != nil {
2689  		return nil, e
2690  	}
2691  	sort.Strings(addrStrs)
2692  	return addrStrs, nil
2693  }
2694  
2695  // NewAddress returns the next external chained address for a wallet.
2696  func (w *Wallet) NewAddress(
2697  	account uint32, scope waddrmgr.KeyScope,
2698  	nochain bool,
2699  ) (addr btcaddr.Address, e error) {
2700  	var (
2701  		chainClient chainclient.Interface
2702  		props       *waddrmgr.AccountProperties
2703  	)
2704  	if !nochain {
2705  		chainClient, e = w.requireChainClient()
2706  		if e != nil {
2707  			return nil, e
2708  		}
2709  	}
2710  	e = walletdb.Update(
2711  		w.db, func(tx walletdb.ReadWriteTx) (e error) {
2712  			addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
2713  			addr, props, e = w.newAddress(addrmgrNs, account, scope)
2714  			return e
2715  		},
2716  	)
2717  	if e != nil {
2718  		return nil, e
2719  	}
2720  	if !nochain {
2721  		// Notify the rpc server about the newly created address.
2722  		e = chainClient.NotifyReceived([]btcaddr.Address{addr})
2723  		if e != nil {
2724  			return nil, e
2725  		}
2726  		w.NtfnServer.notifyAccountProperties(props)
2727  	}
2728  	return addr, nil
2729  }
2730  func (w *Wallet) newAddress(
2731  	addrmgrNs walletdb.ReadWriteBucket, account uint32,
2732  	scope waddrmgr.KeyScope,
2733  ) (btcaddr.Address, *waddrmgr.AccountProperties, error) {
2734  	manager, e := w.Manager.FetchScopedKeyManager(scope)
2735  	if e != nil {
2736  		return nil, nil, e
2737  	}
2738  	// Get next address from wallet.
2739  	var addrs []waddrmgr.ManagedAddress
2740  	if addrs, e = manager.NextExternalAddresses(addrmgrNs, account, 1); E.Chk(e) {
2741  		return nil, nil, e
2742  	}
2743  	var props *waddrmgr.AccountProperties
2744  	if props, e = manager.AccountProperties(addrmgrNs, account); E.Chk(e) {
2745  		E.Ln(
2746  			"cannot fetch account properties for notification after deriving next external address:",
2747  			e,
2748  		)
2749  		return nil, nil, e
2750  	}
2751  	return addrs[0].Address(), props, nil
2752  }
2753  
2754  // NewChangeAddress returns a new change address for a wallet.
2755  func (w *Wallet) NewChangeAddress(
2756  	account uint32,
2757  	scope waddrmgr.KeyScope,
2758  ) (btcaddr.Address, error) {
2759  	chainClient, e := w.requireChainClient()
2760  	if e != nil {
2761  		return nil, e
2762  	}
2763  	var addr btcaddr.Address
2764  	e = walletdb.Update(
2765  		w.db, func(tx walletdb.ReadWriteTx) (e error) {
2766  			addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
2767  			addr, e = w.newChangeAddress(addrmgrNs, account)
2768  			return e
2769  		},
2770  	)
2771  	if e != nil {
2772  		return nil, e
2773  	}
2774  	// Notify the rpc server about the newly created address.
2775  	e = chainClient.NotifyReceived([]btcaddr.Address{addr})
2776  	if e != nil {
2777  		return nil, e
2778  	}
2779  	return addr, nil
2780  }
2781  func (w *Wallet) newChangeAddress(
2782  	addrmgrNs walletdb.ReadWriteBucket,
2783  	account uint32,
2784  ) (btcaddr.Address, error) {
2785  	// As we're making a change address, we'll fetch the type of manager that is able to make p2wkh output as they're
2786  	// the most efficient.
2787  	scopes := w.Manager.ScopesForExternalAddrType(
2788  		waddrmgr.PubKeyHash,
2789  	)
2790  	manager, e := w.Manager.FetchScopedKeyManager(scopes[0])
2791  	if e != nil {
2792  		return nil, e
2793  	}
2794  	// Get next chained change address from wallet for account.
2795  	addrs, e := manager.NextInternalAddresses(addrmgrNs, account, 1)
2796  	if e != nil {
2797  		return nil, e
2798  	}
2799  	return addrs[0].Address(), nil
2800  }
2801  
2802  // confirmed checks whether a transaction at height txHeight has met minconf confirmations for a blockchain at height
2803  // curHeight.
2804  func confirmed(minconf, txHeight, curHeight int32) bool {
2805  	return confirms(txHeight, curHeight) >= minconf
2806  }
2807  
2808  // confirms returns the number of confirmations for a transaction in a block at height txHeight (or -1 for an
2809  // unconfirmed tx) given the chain height curHeight.
2810  func confirms(txHeight, curHeight int32) int32 {
2811  	switch {
2812  	case txHeight == -1, txHeight > curHeight:
2813  		return 0
2814  	default:
2815  		return curHeight - txHeight + 1
2816  	}
2817  }
2818  
2819  // AccountTotalReceivedResult is a single result for the Wallet.TotalReceivedForAccounts method.
2820  type AccountTotalReceivedResult struct {
2821  	AccountNumber    uint32
2822  	AccountName      string
2823  	TotalReceived    amt.Amount
2824  	LastConfirmation int32
2825  }
2826  
2827  // TotalReceivedForAccounts iterates through a wallet's transaction history, returning the total amount of Bitcoin
2828  // received for all accounts.
2829  func (w *Wallet) TotalReceivedForAccounts(
2830  	scope waddrmgr.KeyScope,
2831  	minConf int32,
2832  ) ([]AccountTotalReceivedResult, error) {
2833  	manager, e := w.Manager.FetchScopedKeyManager(scope)
2834  	if e != nil {
2835  		return nil, e
2836  	}
2837  	var results []AccountTotalReceivedResult
2838  	e = walletdb.View(
2839  		w.db, func(tx walletdb.ReadTx) (e error) {
2840  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
2841  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
2842  			syncBlock := w.Manager.SyncedTo()
2843  			e = manager.ForEachAccount(
2844  				addrmgrNs, func(account uint32) (e error) {
2845  					accountName, e := manager.AccountName(addrmgrNs, account)
2846  					if e != nil {
2847  						return e
2848  					}
2849  					results = append(
2850  						results, AccountTotalReceivedResult{
2851  							AccountNumber: account,
2852  							AccountName:   accountName,
2853  						},
2854  					)
2855  					return nil
2856  				},
2857  			)
2858  			if e != nil {
2859  				return e
2860  			}
2861  			var stopHeight int32
2862  			if minConf > 0 {
2863  				stopHeight = syncBlock.Height - minConf + 1
2864  			} else {
2865  				stopHeight = -1
2866  			}
2867  			rangeFn := func(details []wtxmgr.TxDetails) (bool, error) {
2868  				for i := range details {
2869  					detail := &details[i]
2870  					for _, cred := range detail.Credits {
2871  						pkScript := detail.MsgTx.TxOut[cred.Index].PkScript
2872  						var outputAcct uint32
2873  						var addrs []btcaddr.Address
2874  						_, addrs, _, e = txscript.ExtractPkScriptAddrs(pkScript, w.chainParams)
2875  						if e == nil && len(addrs) > 0 {
2876  							_, outputAcct, e = w.Manager.AddrAccount(addrmgrNs, addrs[0])
2877  						}
2878  						if e == nil {
2879  							acctIndex := int(outputAcct)
2880  							if outputAcct == waddrmgr.ImportedAddrAccount {
2881  								acctIndex = len(results) - 1
2882  							}
2883  							res := &results[acctIndex]
2884  							res.TotalReceived += cred.Amount
2885  							res.LastConfirmation = confirms(
2886  								detail.Block.Height, syncBlock.Height,
2887  							)
2888  						}
2889  					}
2890  				}
2891  				return false, nil
2892  			}
2893  			return w.TxStore.RangeTransactions(txmgrNs, 0, stopHeight, rangeFn)
2894  		},
2895  	)
2896  	return results, e
2897  }
2898  
2899  // TotalReceivedForAddr iterates through a wallet's transaction history, returning the total amount of bitcoins received
2900  // for a single wallet address.
2901  func (w *Wallet) TotalReceivedForAddr(
2902  	addr btcaddr.Address, minConf int32,
2903  ) (amount amt.Amount, e error) {
2904  	e = walletdb.View(
2905  		w.db, func(tx walletdb.ReadTx) (e error) {
2906  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
2907  			syncBlock := w.Manager.SyncedTo()
2908  			var (
2909  				addrStr    = addr.EncodeAddress()
2910  				stopHeight int32
2911  			)
2912  			if minConf > 0 {
2913  				stopHeight = syncBlock.Height - minConf + 1
2914  			} else {
2915  				stopHeight = -1
2916  			}
2917  			rangeFn := func(details []wtxmgr.TxDetails) (bool, error) {
2918  				for i := range details {
2919  					detail := &details[i]
2920  					for _, cred := range detail.Credits {
2921  						pkScript := detail.MsgTx.TxOut[cred.Index].PkScript
2922  						var addrs []btcaddr.Address
2923  						_, addrs, _, e = txscript.ExtractPkScriptAddrs(
2924  							pkScript,
2925  							w.chainParams,
2926  						)
2927  						// An error creating addresses from the output script only indicates a non-standard script, so
2928  						// ignore this credit.
2929  						if e != nil {
2930  							continue
2931  						}
2932  						for _, a := range addrs {
2933  							if addrStr == a.EncodeAddress() {
2934  								amount += cred.Amount
2935  								break
2936  							}
2937  						}
2938  					}
2939  				}
2940  				return false, nil
2941  			}
2942  			return w.TxStore.RangeTransactions(txmgrNs, 0, stopHeight, rangeFn)
2943  		},
2944  	)
2945  	return amount, e
2946  }
2947  
2948  // SendOutputs creates and sends payment transactions. It returns the transaction hash upon success.
2949  func (w *Wallet) SendOutputs(
2950  	outputs []*wire.TxOut, account uint32,
2951  	minconf int32, satPerKb amt.Amount,
2952  ) (*chainhash.Hash, error) {
2953  	// Ensure the outputs to be created adhere to the network's consensus rules.
2954  	for _, output := range outputs {
2955  		if e := txrules.CheckOutput(output, satPerKb); E.Chk(e) {
2956  			return nil, e
2957  		}
2958  	}
2959  	// Create the transaction and broadcast it to the network. The transaction will be added to the database in order to
2960  	// ensure that we continue to re-broadcast the transaction upon restarts until it has been confirmed.
2961  	createdTx, e := w.CreateSimpleTx(account, outputs, minconf, satPerKb)
2962  	if e != nil {
2963  		return nil, e
2964  	}
2965  	D.S(createdTx)
2966  	return w.publishTransaction(createdTx.Tx)
2967  }
2968  
2969  // SignatureError records the underlying error when validating a transaction input signature.
2970  type SignatureError struct {
2971  	InputIndex uint32
2972  	Error      error
2973  }
2974  
2975  // SignTransaction uses secrets of the wallet, as well as additional secrets
2976  // passed in by the caller, to create and add input signatures to a transaction.
2977  //
2978  // Transaction input script validation is used to confirm that all signatures
2979  // are valid. For any invalid input, a SignatureError is added to the returns.
2980  // The final error return is reserved for unexpected or fatal errors, such as
2981  // being unable to determine a previous output script to redeem.
2982  //
2983  // The transaction pointed to by tx is modified by this function.
2984  func (w *Wallet) SignTransaction(
2985  	tx *wire.MsgTx, hashType txscript.SigHashType,
2986  	additionalPrevScripts map[wire.OutPoint][]byte,
2987  	additionalKeysByAddress map[string]*util.WIF,
2988  	p2shRedeemScriptsByAddress map[string][]byte,
2989  ) (signErrors []SignatureError, e error) {
2990  	I.Ln("signing transaction")
2991  	I.S(tx)
2992  	e = walletdb.View(
2993  		w.db, func(dbtx walletdb.ReadTx) (e error) {
2994  			addrmgrNs := dbtx.ReadBucket(waddrmgrNamespaceKey)
2995  			txmgrNs := dbtx.ReadBucket(wtxmgrNamespaceKey)
2996  			for i, txIn := range tx.TxIn {
2997  				prevOutScript, ok := additionalPrevScripts[txIn.PreviousOutPoint]
2998  				if !ok {
2999  					prevHash := &txIn.PreviousOutPoint.Hash
3000  					prevIndex := txIn.PreviousOutPoint.Index
3001  					var txDetails *wtxmgr.TxDetails
3002  					txDetails, e = w.TxStore.TxDetails(txmgrNs, prevHash)
3003  					if e != nil {
3004  						return fmt.Errorf(
3005  							"cannot query previous transaction details for %v: %v",
3006  							txIn.PreviousOutPoint, e,
3007  						)
3008  					}
3009  					if txDetails == nil {
3010  						return fmt.Errorf(
3011  							"%v not found",
3012  							txIn.PreviousOutPoint,
3013  						)
3014  					}
3015  					prevOutScript = txDetails.MsgTx.TxOut[prevIndex].PkScript
3016  				}
3017  				// Set up our callbacks that we pass to txscript so it can look up the
3018  				// appropriate keys and scripts by address.
3019  				getKey := txscript.KeyClosure(
3020  					func(addr btcaddr.Address) (*ec.PrivateKey, bool, error) {
3021  						if len(additionalKeysByAddress) != 0 {
3022  							addrStr := addr.EncodeAddress()
3023  							var wif *util.WIF
3024  							wif, ok = additionalKeysByAddress[addrStr]
3025  							if !ok {
3026  								return nil, false,
3027  									errors.New("no key for address")
3028  							}
3029  							return wif.PrivKey, wif.CompressPubKey, nil
3030  						}
3031  						var address waddrmgr.ManagedAddress
3032  						address, e = w.Manager.Address(addrmgrNs, addr)
3033  						if e != nil {
3034  							return nil, false, e
3035  						}
3036  						var pka waddrmgr.ManagedPubKeyAddress
3037  						pka, ok = address.(waddrmgr.ManagedPubKeyAddress)
3038  						if !ok {
3039  							return nil, false, fmt.Errorf(
3040  								"address %v is not "+
3041  									"a pubkey address", address.Address().EncodeAddress(),
3042  							)
3043  						}
3044  						var key *ec.PrivateKey
3045  						key, e = pka.PrivKey()
3046  						if e != nil {
3047  							return nil, false, e
3048  						}
3049  						return key, pka.Compressed(), nil
3050  					},
3051  				)
3052  				getScript := txscript.ScriptClosure(
3053  					func(addr btcaddr.Address) ([]byte, error) {
3054  						// If keys were provided then we can only use the redeem scripts provided with
3055  						// our inputs, too.
3056  						if len(additionalKeysByAddress) != 0 {
3057  							addrStr := addr.EncodeAddress()
3058  							script, ok := p2shRedeemScriptsByAddress[addrStr]
3059  							if !ok {
3060  								return nil, errors.New("no script for address")
3061  							}
3062  							return script, nil
3063  						}
3064  						address, e := w.Manager.Address(addrmgrNs, addr)
3065  						if e != nil {
3066  							return nil, e
3067  						}
3068  						sa, ok := address.(waddrmgr.ManagedScriptAddress)
3069  						if !ok {
3070  							return nil, errors.New(
3071  								"address is not a script" +
3072  									" address",
3073  							)
3074  						}
3075  						return sa.Script()
3076  					},
3077  				)
3078  				// SigHashSingle inputs can only be signed if there's a corresponding output. However this could be already
3079  				// signed, so we always verify the output.
3080  				if (hashType&txscript.SigHashSingle) !=
3081  					txscript.SigHashSingle || i < len(tx.TxOut) {
3082  					script, e := txscript.SignTxOutput(
3083  						w.ChainParams(),
3084  						tx, i, prevOutScript, hashType, getKey,
3085  						getScript, txIn.SignatureScript,
3086  					)
3087  					// Failure to sign isn't an error, it just means that the tx isn't complete.
3088  					if e != nil {
3089  						signErrors = append(
3090  							signErrors, SignatureError{
3091  								InputIndex: uint32(i),
3092  								Error:      e,
3093  							},
3094  						)
3095  						continue
3096  					}
3097  					txIn.SignatureScript = script
3098  				}
3099  				// Either it was already signed or we just signed it. Find out if it is completely satisfied or still needs
3100  				// more.
3101  				vm, e := txscript.NewEngine(
3102  					prevOutScript, tx, i,
3103  					txscript.StandardVerifyFlags, nil, nil, 0,
3104  				)
3105  				if e == nil {
3106  					e = vm.Execute()
3107  				}
3108  				if e != nil {
3109  					signErrors = append(
3110  						signErrors, SignatureError{
3111  							InputIndex: uint32(i),
3112  							Error:      e,
3113  						},
3114  					)
3115  				}
3116  			}
3117  			return nil
3118  		},
3119  	)
3120  	return signErrors, e
3121  }
3122  
3123  // PublishTransaction sends the transaction to the consensus RPC server so it can be propagated to other nodes and
3124  // eventually mined.
3125  //
3126  // This function is unstable and will be removed once syncing code is moved out of the wallet.
3127  func (w *Wallet) PublishTransaction(tx *wire.MsgTx) (e error) {
3128  	_, e = w.publishTransaction(tx)
3129  	return e
3130  }
3131  
3132  // publishTransaction is the private version of PublishTransaction which contains the primary logic required for
3133  // publishing a transaction, updating the relevant database state, and finally possible removing the transaction from
3134  // the database (along with cleaning up all inputs used, and outputs created) if the transaction is rejected by the back
3135  // end.
3136  func (w *Wallet) publishTransaction(tx *wire.MsgTx) (*chainhash.Hash, error) {
3137  	server, e := w.requireChainClient()
3138  	if e != nil {
3139  		return nil, e
3140  	}
3141  	// As we aim for this to be general reliable transaction broadcast API, we'll write this tx to disk as an
3142  	// unconfirmed transaction. This way, upon restarts, we'll always rebroadcast it, and also add it to our set of
3143  	// records.
3144  	txRec, e := wtxmgr.NewTxRecordFromMsgTx(tx, time.Now())
3145  	if e != nil {
3146  		return nil, e
3147  	}
3148  	e = walletdb.Update(
3149  		w.db, func(dbTx walletdb.ReadWriteTx) (e error) {
3150  			return w.addRelevantTx(dbTx, txRec, nil)
3151  		},
3152  	)
3153  	if e != nil {
3154  		return nil, e
3155  	}
3156  	txid, e := server.SendRawTransaction(tx, false)
3157  	switch {
3158  	case e == nil:
3159  		return txid, nil
3160  	// The following are errors returned from pod's mempool.
3161  	case strings.Contains(e.Error(), "spent"):
3162  		fallthrough
3163  	case strings.Contains(e.Error(), "orphan"):
3164  		fallthrough
3165  	case strings.Contains(e.Error(), "conflict"):
3166  		fallthrough
3167  	// The following errors are returned from bitcoind's mempool.
3168  	case strings.Contains(e.Error(), "fee not met"):
3169  		fallthrough
3170  	case strings.Contains(e.Error(), "Missing inputs"):
3171  		fallthrough
3172  	case strings.Contains(e.Error(), "already in block chain"):
3173  		// If the transaction was rejected, then we'll remove it from the txstore, as otherwise, we'll attempt to
3174  		// continually re-broadcast it, and the utxo state of the wallet won't be accurate.
3175  		dbErr := walletdb.Update(
3176  			w.db, func(dbTx walletdb.ReadWriteTx) (e error) {
3177  				txmgrNs := dbTx.ReadWriteBucket(wtxmgrNamespaceKey)
3178  				return w.TxStore.RemoveUnminedTx(txmgrNs, txRec)
3179  			},
3180  		)
3181  		if dbErr != nil {
3182  			return nil, fmt.Errorf(
3183  				"unable to broadcast tx: %v, "+
3184  					"unable to remove invalid tx: %v", e, dbErr,
3185  			)
3186  		}
3187  		return nil, e
3188  	default:
3189  		return nil, e
3190  	}
3191  }
3192  
3193  // ChainParams returns the network parameters for the blockchain the wallet belongs to.
3194  func (w *Wallet) ChainParams() *chaincfg.Params {
3195  	return w.chainParams
3196  }
3197  
3198  // Database returns the underlying walletdb database. This method is provided in order to allow applications wrapping
3199  // btcwallet to store node-specific data with the wallet's database.
3200  func (w *Wallet) Database() walletdb.DB {
3201  	return w.db
3202  }
3203  
3204  // Create creates an new wallet, writing it to an empty database. If the passed seed is non-nil, it is used. Otherwise,
3205  // a secure random seed of the recommended length is generated.
3206  func Create(
3207  	db walletdb.DB, pubPass, privPass, seed []byte, params *chaincfg.Params,
3208  	birthday time.Time,
3209  ) (e error) {
3210  	// If a seed was provided, ensure that it is of valid length. Otherwise, we generate a random seed for the wallet
3211  	// with the recommended seed length.
3212  	if seed == nil {
3213  		hdSeed, e := hdkeychain.GenerateSeed(
3214  			hdkeychain.RecommendedSeedLen,
3215  		)
3216  		if e != nil {
3217  			return e
3218  		}
3219  		seed = hdSeed
3220  	}
3221  	if len(seed) < hdkeychain.MinSeedBytes ||
3222  		len(seed) > hdkeychain.MaxSeedBytes {
3223  		return hdkeychain.ErrInvalidSeedLen
3224  	}
3225  	return walletdb.Update(
3226  		db, func(tx walletdb.ReadWriteTx) (e error) {
3227  			addrmgrNs, e := tx.CreateTopLevelBucket(waddrmgrNamespaceKey)
3228  			if e != nil {
3229  				return e
3230  			}
3231  			txmgrNs, e := tx.CreateTopLevelBucket(wtxmgrNamespaceKey)
3232  			if e != nil {
3233  				return e
3234  			}
3235  			e = waddrmgr.Create(
3236  				addrmgrNs, seed, pubPass, privPass, params, nil,
3237  				birthday,
3238  			)
3239  			if e != nil {
3240  				return e
3241  			}
3242  			return wtxmgr.Create(txmgrNs)
3243  		},
3244  	)
3245  }
3246  
3247  // Open loads an already-created wallet from the passed database and namespaces.
3248  func Open(
3249  	db walletdb.DB,
3250  	pubPass []byte,
3251  	cbs *waddrmgr.OpenCallbacks,
3252  	params *chaincfg.Params,
3253  	recoveryWindow uint32,
3254  	podConfig *config.Config,
3255  	quit qu.C,
3256  ) (*Wallet, error) {
3257  	// debug.PrintStack()
3258  	W.Ln("opening wallet") // , string(pubPass))
3259  	e := walletdb.View(
3260  		db, func(tx walletdb.ReadTx) (e error) {
3261  			waddrmgrBucket := tx.ReadBucket(waddrmgrNamespaceKey)
3262  			if waddrmgrBucket == nil {
3263  				return errors.New("missing address manager namespace")
3264  			}
3265  			wtxmgrBucket := tx.ReadBucket(wtxmgrNamespaceKey)
3266  			if wtxmgrBucket == nil {
3267  				return errors.New("missing transaction manager namespace")
3268  			}
3269  			return nil
3270  		},
3271  	)
3272  	if e != nil {
3273  		return nil, e
3274  	}
3275  	T.Ln("opened wallet")
3276  	// Perform upgrades as necessary. Each upgrade is done under its own transaction, which is managed by each package
3277  	// itself, so the entire DB is passed instead of passing already opened write transaction.
3278  	//
3279  	// This will need to change later when upgrades in one package depend on data in another (such as removing chain
3280  	// synchronization from address manager).
3281  	T.Ln("doing address manager upgrades")
3282  	e = waddrmgr.DoUpgrades(db, waddrmgrNamespaceKey, pubPass, params, cbs)
3283  	if e != nil {
3284  		return nil, e
3285  	}
3286  	T.Ln("doing txmanager upgrades")
3287  	e = wtxmgr.DoUpgrades(db, wtxmgrNamespaceKey)
3288  	if e != nil {
3289  		return nil, e
3290  	}
3291  	// Open database abstraction instances
3292  	var (
3293  		addrMgr *waddrmgr.Manager
3294  		txMgr   *wtxmgr.Store
3295  	)
3296  	T.Ln("opening wallet database abstraction instances")
3297  	e = walletdb.View(
3298  		db, func(tx walletdb.ReadTx) (e error) {
3299  			T.Ln("reading address bucket")
3300  			addrmgrNs := tx.ReadBucket(waddrmgrNamespaceKey)
3301  			T.Ln("reading tx bucket")
3302  			txmgrNs := tx.ReadBucket(wtxmgrNamespaceKey)
3303  			T.Ln("opening address manager")
3304  			addrMgr, e = waddrmgr.Open(addrmgrNs, pubPass, params)
3305  			if e != nil {
3306  				E.Ln(e, "'"+string(pubPass)+"'")
3307  				return e
3308  			}
3309  			T.Ln("opening transaction manager")
3310  			txMgr, e = wtxmgr.Open(txmgrNs, params)
3311  			T.Ln("wallet database abstraction instances opened")
3312  			return e
3313  		},
3314  	)
3315  	if e != nil {
3316  		return nil, e
3317  	}
3318  	T.Ln("creating wallet state") // TODO: log balance? last sync height?
3319  	w := &Wallet{
3320  		publicPassphrase:    pubPass,
3321  		db:                  db,
3322  		Manager:             addrMgr,
3323  		TxStore:             txMgr,
3324  		lockedOutpoints:     map[wire.OutPoint]struct{}{},
3325  		recoveryWindow:      recoveryWindow,
3326  		rescanAddJob:        make(chan *RescanJob),
3327  		rescanBatch:         make(chan *rescanBatch),
3328  		rescanNotifications: make(chan interface{}),
3329  		rescanProgress:      make(chan *RescanProgressMsg),
3330  		rescanFinished:      make(chan *RescanFinishedMsg),
3331  		createTxRequests:    make(chan createTxRequest),
3332  		unlockRequests:      make(chan unlockRequest),
3333  		lockRequests:        qu.T(),
3334  		holdUnlockRequests:  make(chan chan heldUnlock),
3335  		lockState:           make(chan bool),
3336  		changePassphrase:    make(chan changePassphraseRequest),
3337  		changePassphrases:   make(chan changePassphrasesRequest),
3338  		chainParams:         params,
3339  		PodConfig:           podConfig,
3340  		quit:                quit,
3341  	}
3342  	w.NtfnServer = newNotificationServer(w)
3343  	w.TxStore.NotifyUnspent = func(hash *chainhash.Hash, index uint32) {
3344  		w.NtfnServer.notifyUnspentOutput(0, hash, index)
3345  	}
3346  	T.Ln("wallet state created")
3347  	return w, nil
3348  }
3349