func fetchWatchingOnly(ns walletdb.ReadBucket) (bool, error) {
	bucket := ns.NestedReadBucket(mainBucketName)
	buf := bucket.Get(watchingOnlyName)
	if len(buf) != 1 {
		return false, errors.E(errors.IO, errors.Errorf("bad watching-only flag len %d", len(buf)))
	}
	return buf[0] != 0, nil
}
fetchWatchingOnly loads the watching-only flag from the database.
package udb
import (
	"crypto/sha256"
	"encoding/binary"
	"time"
	"decred.org/dcrwallet/v2/errors"
	"decred.org/dcrwallet/v2/kdf"
	"decred.org/dcrwallet/v2/wallet/walletdb"
)
var (
	latestMgrVersion uint32 = 6
)
type ObtainUserInputFunc func() ([]byte, error)
type addressType uint8
const (
	adtChain  addressType = iota  
	adtImport                     
	adtScript                     
)
type dbAccount interface {
	accountType() accountType
	rowData() []byte
}
type accountType uint8
const (
	actBIP0044Legacy accountType = iota
	actBIP0044
)
type dbAccountRow struct {
	acctType accountType
	rawData  []byte  
}
type dbBIP0044AccountRow struct {
	dbAccountRow
	pubKeyEncrypted           []byte
	privKeyEncrypted          []byte
	nextExternalIndex         uint32  
	nextInternalIndex         uint32  
	lastUsedExternalIndex     uint32  
	lastUsedInternalIndex     uint32  
	lastReturnedExternalIndex uint32  
	lastReturnedInternalIndex uint32  
	name                      string
	uniqueKey *kdf.Argon2idParams
}
func (r *dbBIP0044AccountRow) accountType() accountType { return actBIP0044Legacy }
func (r *dbBIP0044AccountRow) rowData() []byte          { return r.dbAccountRow.rawData }
type dbBIP0044Account struct {
	dbAccountRow
	pubKeyEncrypted  []byte
	privKeyEncrypted []byte
	lastUsedExternalIndex     uint32
	lastUsedInternalIndex     uint32
	lastReturnedExternalIndex uint32
	lastReturnedInternalIndex uint32
	name                      string
	uniqueKey                 *kdf.Argon2idParams
}
func (a *dbBIP0044Account) accountType() accountType { return actBIP0044 }
func (a *dbBIP0044Account) rowData() []byte          { return a.dbAccountRow.rawData }
func (a *dbBIP0044Account) serializeRow() []byte {
	data := make([]byte, 8+len(a.pubKeyEncrypted)+len(a.privKeyEncrypted))
	binary.LittleEndian.PutUint32(data, uint32(len(a.pubKeyEncrypted)))
	off := 4
	off += copy(data[off:], a.pubKeyEncrypted)
	binary.LittleEndian.PutUint32(data[off:], uint32(len(a.privKeyEncrypted)))
	off += 4
	copy(data[off:], a.privKeyEncrypted)
	a.rawData = data
	return data
}
func (a *dbBIP0044Account) deserializeRow(v []byte) error {
	if len(v) < 8 {
		err := errors.Errorf("BIP0044 account row bad len %d", len(v))
		return errors.E(errors.IO, err)
	}
	encPubLen := binary.LittleEndian.Uint32(v)
	off := uint32(4)
	encPub := append([]byte(nil), v[off:off+encPubLen]...)
	off += encPubLen
	encPrivLen := binary.LittleEndian.Uint32(v[off:])
	off += 4
	encPriv := append([]byte(nil), v[off:off+encPrivLen]...)
	off += encPrivLen
	if int(off) != len(v) {
		return errors.E(errors.IO, "extra bytes in BIP0044 account row")
	}
	a.pubKeyEncrypted = encPub
	a.privKeyEncrypted = encPriv
	a.rawData = v
	return nil
}
type dbAddressRow struct {
	addrType addressType
	account  uint32
	addTime  uint64
	rawData  []byte  
}
type dbChainAddressRow struct {
	dbAddressRow
	branch uint32
	index  uint32
}
type dbImportedAddressRow struct {
	dbAddressRow
	encryptedPubKey  []byte
	encryptedPrivKey []byte
}
type dbScriptAddressRow struct {
	dbAddressRow
	encryptedHash []byte
	script        []byte
}
var (
	nullVal = []byte{0}
	acctBucketName     = []byte("acct")
	acctVarsBucketName = []byte("acctvars")
	addrBucketName     = []byte("addr")
	addrAcctIdxBucketName = []byte("addracctidx")
	acctNameIdxBucketName = []byte("acctnameidx")
	acctIDIdxBucketName = []byte("acctididx")
	metaBucketName = []byte("meta")
	addrPoolMetaKeyLen = 15
	addrPoolKeyPrefixExt = []byte("addrpoolext")
	addrPoolKeyPrefixInt = []byte("addrpoolint")
	lastAccountName = []byte("lastaccount")
	lastImportedAccountName = []byte("lastimportedaccount")
	mainBucketName = []byte("main")
	mgrVersionName    = []byte("mgrver")
	mgrCreateDateName = []byte("mgrcreated")
	seedName                    = []byte("seed")
	masterPrivKeyName           = []byte("mpriv")
	masterPubKeyName            = []byte("mpub")
	cryptoPrivKeyName           = []byte("cpriv")
	cryptoPubKeyName            = []byte("cpub")
	cryptoScriptKeyName         = []byte("cscript")  
	coinTypeLegacyPrivKeyName   = []byte("ctpriv")
	coinTypeLegacyPubKeyName    = []byte("ctpub")
	coinTypeSLIP0044PrivKeyName = []byte("ctpriv-slip0044")
	coinTypeSLIP0044PubKeyName  = []byte("ctpub-slip0044")
	watchingOnlyName            = []byte("watchonly")
	slip0044Account0RowName     = []byte("slip0044acct0")
	usedAddrBucketName = []byte("usedaddrs")
)
func uint32ToBytes(number uint32) []byte {
	buf := make([]byte, 4)
	binary.LittleEndian.PutUint32(buf, number)
	return buf
}
func stringToBytes(s string) []byte {
	size := len(s)
	buf := make([]byte, 4+size)
	copy(buf[0:4], uint32ToBytes(uint32(size)))
	copy(buf[4:4+size], s)
	return buf
}
func fetchManagerVersion(ns walletdb.ReadBucket) (uint32, error) {
	mainBucket := ns.NestedReadBucket(mainBucketName)
	verBytes := mainBucket.Get(mgrVersionName)
	if verBytes == nil {
		return 0, errors.E(errors.IO, "missing address manager version")
	}
	version := binary.LittleEndian.Uint32(verBytes)
	return version, nil
}
func putManagerVersion(ns walletdb.ReadWriteBucket, version uint32) error {
	bucket := ns.NestedReadWriteBucket(mainBucketName)
	verBytes := uint32ToBytes(version)
	err := bucket.Put(mgrVersionName, verBytes)
	if err != nil {
		return errors.E(errors.IO, err)
	}
	return nil
}
func fetchMasterKeyParams(ns walletdb.ReadBucket) ([]byte, []byte, error) {
	bucket := ns.NestedReadBucket(mainBucketName)
	val := bucket.Get(masterPubKeyName)
	if val == nil {
		return nil, nil, errors.E(errors.IO, "missing master pubkey params")
	}
	pubParams := make([]byte, len(val))
	copy(pubParams, val)
	var privParams []byte
	val = bucket.Get(masterPrivKeyName)
	if val != nil {
		privParams = make([]byte, len(val))
		copy(privParams, val)
	}
	return pubParams, privParams, nil
}
func putMasterKeyParams(ns walletdb.ReadWriteBucket, pubParams, privParams []byte) error {
	bucket := ns.NestedReadWriteBucket(mainBucketName)
	if privParams != nil {
		err := bucket.Put(masterPrivKeyName, privParams)
		if err != nil {
			return errors.E(errors.IO, err)
		}
	}
	if pubParams != nil {
		err := bucket.Put(masterPubKeyName, pubParams)
		if err != nil {
			return errors.E(errors.IO, err)
		}
	}
	return nil
}
func fetchCoinTypeKeys(ns walletdb.ReadBucket) ([]byte, []byte, error) {
	bucket := ns.NestedReadBucket(mainBucketName)
	var coinTypeSLIP0044 bool
	coinTypePubKeyEnc := bucket.Get(coinTypeLegacyPubKeyName)
	if coinTypePubKeyEnc == nil {
		coinTypeSLIP0044 = true
		coinTypePubKeyEnc = bucket.Get(coinTypeSLIP0044PubKeyName)
	}
	if coinTypePubKeyEnc == nil {
		return nil, nil, errors.E(errors.IO, "missing encrypted cointype pubkey")
	}
	coinTypePrivKeyName := coinTypeLegacyPrivKeyName
	if coinTypeSLIP0044 {
		coinTypePrivKeyName = coinTypeSLIP0044PrivKeyName
	}
	coinTypePrivKeyEnc := bucket.Get(coinTypePrivKeyName)
	if coinTypePrivKeyEnc == nil {
		return nil, nil, errors.E(errors.IO, "missing encrypted cointype privkey")
	}
	return coinTypePubKeyEnc, coinTypePrivKeyEnc, nil
}
func putCoinTypeLegacyKeys(ns walletdb.ReadWriteBucket, coinTypePubKeyEnc []byte, coinTypePrivKeyEnc []byte) error {
	bucket := ns.NestedReadWriteBucket(mainBucketName)
	if coinTypePubKeyEnc != nil {
		err := bucket.Put(coinTypeLegacyPubKeyName, coinTypePubKeyEnc)
		if err != nil {
			return errors.E(errors.IO, err)
		}
	}
	if coinTypePrivKeyEnc != nil {
		err := bucket.Put(coinTypeLegacyPrivKeyName, coinTypePrivKeyEnc)
		if err != nil {
			return errors.E(errors.IO, err)
		}
	}
	return nil
}
func putCoinTypeSLIP0044Keys(ns walletdb.ReadWriteBucket, coinTypePubKeyEnc []byte, coinTypePrivKeyEnc []byte) error {
	bucket := ns.NestedReadWriteBucket(mainBucketName)
	if coinTypePubKeyEnc != nil {
		err := bucket.Put(coinTypeSLIP0044PubKeyName, coinTypePubKeyEnc)
		if err != nil {
			return errors.E(errors.IO, err)
		}
	}
	if coinTypePrivKeyEnc != nil {
		err := bucket.Put(coinTypeSLIP0044PrivKeyName, coinTypePrivKeyEnc)
		if err != nil {
			return errors.E(errors.IO, err)
		}
	}
	return nil
}
func fetchCryptoKeys(ns walletdb.ReadBucket) ([]byte, []byte, error) {
	bucket := ns.NestedReadBucket(mainBucketName)
	val := bucket.Get(cryptoPubKeyName)
	if val == nil {
		return nil, nil, errors.E(errors.IO, "missing encrypted crypto pubkey")
	}
	pubKey := make([]byte, len(val))
	copy(pubKey, val)
	var privKey []byte
	val = bucket.Get(cryptoPrivKeyName)
	if val != nil {
		privKey = make([]byte, len(val))
		copy(privKey, val)
	}
	return pubKey, privKey, nil
}
func putCryptoKeys(ns walletdb.ReadWriteBucket, pubKeyEncrypted, privKeyEncrypted []byte) error {
	bucket := ns.NestedReadWriteBucket(mainBucketName)
	if pubKeyEncrypted != nil {
		err := bucket.Put(cryptoPubKeyName, pubKeyEncrypted)
		if err != nil {
			return errors.E(errors.IO, err)
		}
	}
	if privKeyEncrypted != nil {
		err := bucket.Put(cryptoPrivKeyName, privKeyEncrypted)
		if err != nil {
			return errors.E(errors.IO, err)
		}
	}
	return nil
}