func fetchWatchingOnly(ns walletdb.ReadBucket) (bool, error) {
	bucket := ns.NestedReadBucket(mainBucketName)
	buf := bucket.Get(watchingOnlyName)
	if len(buf) != 1 {
		str := "malformed watching-only flag stored in database"
		return false, managerError(apperrors.ErrDatabase, str, nil)
	}
	return buf[0] != 0, nil
}
fetchWatchingOnly loads the watching-only flag from the database.
package udb
import (
	"crypto/sha256"
	"encoding/binary"
	"fmt"
	"time"
	"github.com/HcashOrg/hcashutil"
	"github.com/HcashOrg/hcashwallet/apperrors"
	"github.com/HcashOrg/hcashwallet/walletdb"
)
var (
	latestMgrVersion uint32 = 6
)
type ObtainUserInputFunc func() ([]byte, error)
func maybeConvertDbError(err error) error {
	if _, ok := err.(apperrors.E); ok {
		return err
	}
	return managerError(apperrors.ErrDatabase, err.Error(), err)
}
type syncStatus uint8
const (
	SSNone    syncStatus = 0  
	SSPartial syncStatus = 1
	SSFull    syncStatus = 2
)
type addressType uint8
const (
	adtChain  addressType = 0  
	adtImport addressType = 1
	adtScript addressType = 2
)
type accountType uint8
const (
	actBIP0044 uint8 = 0  
	actBliss   uint8 = 1
	actMSS     uint8 = 2
)
type dbAccountRow struct {
	acctType uint8
	rawData  []byte  
}
type dbBIP0044AccountRow struct {
	dbAccountRow
	pubKeyEncrypted           []byte
	privKeyEncrypted          []byte
	nextExternalIndex         uint32  
	nextInternalIndex         uint32  
	lastUsedExternalIndex     uint32  
	lastUsedInternalIndex     uint32  
	lastReturnedExternalIndex uint32  
	lastReturnedInternalIndex uint32  
	name                      string
}
type dbAddressRow struct {
	addrType   addressType
	account    uint32
	addTime    uint64
	syncStatus syncStatus
	rawData    []byte  
}
type dbChainAddressRow struct {
	dbAddressRow
	branch uint32
	index  uint32
}
type dbImportedAddressRow struct {
	dbAddressRow
	encryptedPubKey  []byte
	encryptedPrivKey []byte
	algType          uint8
}
type dbScriptAddressRow struct {
	dbAddressRow
	encryptedHash   []byte
	encryptedScript []byte
}
var (
	nullVal = []byte{0}
	acctBucketName = []byte("acct")
	addrBucketName = []byte("addr")
	addrAcctIdxBucketName = []byte("addracctidx")
	acctNameIdxBucketName = []byte("acctnameidx")
	acctIDIdxBucketName = []byte("acctididx")
	metaBucketName = []byte("meta")
	blissaddrIdxBucketName = []byte("blissaddridx")
	addrPoolMetaKeyLen = 15
	addrPoolKeyPrefixExt = []byte("addrpoolext")
	addrPoolKeyPrefixInt = []byte("addrpoolint")
	lastAccountName = []byte("lastaccount")
	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")
	coinTypePrivKeyName = []byte("ctpriv")
	coinTypePubKeyName  = []byte("ctpub")
	watchingOnlyName    = []byte("watchonly")
	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 {
		str := "required version number not stored in database"
		return 0, managerError(apperrors.ErrDatabase, str, nil)
	}
	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 {
		str := "failed to store version"
		return managerError(apperrors.ErrDatabase, str, err)
	}
	return nil
}
func fetchMasterKeyParams(ns walletdb.ReadBucket) ([]byte, []byte, error) {
	bucket := ns.NestedReadBucket(mainBucketName)
	val := bucket.Get(masterPubKeyName)
	if val == nil {
		str := "required master public key parameters not stored in " +
			"database"
		return nil, nil, managerError(apperrors.ErrDatabase, str, nil)
	}
	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 {
			str := "failed to store master private key parameters"
			return managerError(apperrors.ErrDatabase, str, err)
		}
	}
	if pubParams != nil {
		err := bucket.Put(masterPubKeyName, pubParams)
		if err != nil {
			str := "failed to store master public key parameters"
			return managerError(apperrors.ErrDatabase, str, err)
		}
	}
	return nil
}
func fetchCoinTypeKeys(ns walletdb.ReadBucket) ([]byte, []byte, error) {
	bucket := ns.NestedReadBucket(mainBucketName)
	coinTypePubKeyEnc := bucket.Get(coinTypePubKeyName)
	if coinTypePubKeyEnc == nil {
		str := "required encrypted cointype public key not stored in database"
		return nil, nil, managerError(apperrors.ErrDatabase, str, nil)
	}
	coinTypePrivKeyEnc := bucket.Get(coinTypePrivKeyName)
	if coinTypePrivKeyEnc == nil {
		str := "required encrypted cointype private key not stored in database"
		return nil, nil, managerError(apperrors.ErrDatabase, str, nil)
	}
	return coinTypePubKeyEnc, coinTypePrivKeyEnc, nil
}
func putCoinTypeKeys(ns walletdb.ReadWriteBucket, coinTypePubKeyEnc []byte, coinTypePrivKeyEnc []byte) error {
	bucket := ns.NestedReadWriteBucket(mainBucketName)
	if coinTypePubKeyEnc != nil {
		err := bucket.Put(coinTypePubKeyName, coinTypePubKeyEnc)
		if err != nil {
			str := "failed to store encrypted cointype public key"
			return managerError(apperrors.ErrDatabase, str, err)
		}
	}
	if coinTypePrivKeyEnc != nil {
		err := bucket.Put(coinTypePrivKeyName, coinTypePrivKeyEnc)
		if err != nil {
			str := "failed to store encrypted cointype private key"
			return managerError(apperrors.ErrDatabase, str, err)
		}
	}
	return nil
}
func fetchCryptoKeys(ns walletdb.ReadBucket) ([]byte, []byte, []byte, error) {
	bucket := ns.NestedReadBucket(mainBucketName)
	val := bucket.Get(cryptoPubKeyName)
	if val == nil {
		str := "required encrypted crypto public not stored in database"
		return nil, nil, nil, managerError(apperrors.ErrDatabase, str, nil)
	}
	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)
	}
	var scriptKey []byte
	val = bucket.Get(cryptoScriptKeyName)
	if val != nil {
		scriptKey = make([]byte, len(val))
		copy(scriptKey, val)
	}
	return pubKey, privKey, scriptKey, nil
}
func putCryptoKeys(ns walletdb.ReadWriteBucket, pubKeyEncrypted, privKeyEncrypted, scriptKeyEncrypted []byte) error {
	bucket := ns.NestedReadWriteBucket(mainBucketName)
	if pubKeyEncrypted != nil {
		err := bucket.Put(cryptoPubKeyName, pubKeyEncrypted)
		if err != nil {
			str := "failed to store encrypted crypto public key"
			return managerError(apperrors.ErrDatabase, str, err)
		}
	}
	if privKeyEncrypted != nil {
		err := bucket.Put(cryptoPrivKeyName, privKeyEncrypted)
		if err != nil {
			str := "failed to store encrypted crypto private key"
			return managerError(apperrors.ErrDatabase, str, err)
		}
	}
	if scriptKeyEncrypted != nil {
		err := bucket.Put(cryptoScriptKeyName, scriptKeyEncrypted)
		if err != nil {
			str := "failed to store encrypted crypto script key"
			return managerError(apperrors.ErrDatabase, str, err)
		}
	}
	return nil
}