import: add support for watchonly addresses/pubkeys [WIP] #23
4 changed files with 67 additions and 22 deletions
|
@ -920,6 +920,9 @@ func getReceivedByAccount(icmd interface{}, w *wallet.Wallet) (interface{}, erro
|
|||
return nil, err
|
||||
}
|
||||
acctIndex := int(account)
|
||||
if account == waddrmgr.ImportedWatchonlyAddrAccount {
|
||||
acctIndex = len(results) - 2
|
||||
}
|
||||
if account == waddrmgr.ImportedAddrAccount {
|
||||
acctIndex = len(results) - 1
|
||||
}
|
||||
|
@ -1692,7 +1695,7 @@ func sendToAddress(icmd interface{}, w *wallet.Wallet) (interface{}, error) {
|
|||
}
|
||||
|
||||
// sendtoaddress always spends from the default account, this matches bitcoind
|
||||
return sendPairs(w, pairs, waddrmgr.KeyScopeBIP0044, waddrmgr.DefaultAccountNum, 1,
|
||||
return sendPairs(w, pairs, waddrmgr.KeyScopeBIP0084, waddrmgr.DefaultAccountNum, 1,
|
||||
txrules.DefaultRelayFeePerKb)
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,8 @@ func isReservedAccountName(name string) bool {
|
|||
// isReservedAccountNum returns true if the account number is reserved.
|
||||
// Reserved accounts may not be renamed.
|
||||
func isReservedAccountNum(acct uint32) bool {
|
||||
return acct == ImportedAddrAccount
|
||||
return acct == ImportedAddrAccount ||
|
||||
acct == ImportedWatchonlyAddrAccount
|
||||
}
|
||||
|
||||
// ScryptOptions is used to hold the scrypt parameters needed when deriving new
|
||||
|
@ -428,6 +429,7 @@ func (m *Manager) IsWatchOnlyAccount(ns walletdb.ReadBucket, keyScope KeyScope,
|
|||
if account == ImportedAddrAccount {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if account == ImportedWatchonlyAddrAccount {
|
||||
return true, nil
|
||||
}
|
||||
|
@ -1785,10 +1787,23 @@ func createManagerKeyScope(ns walletdb.ReadWriteBucket,
|
|||
return err
|
||||
}
|
||||
|
||||
return putDefaultAccountInfo(
|
||||
err = putDefaultAccountInfo(
|
||||
ns, &scope, ImportedAddrAccount, nil, nil, 0, 0,
|
||||
ImportedAddrAccountName,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = putDefaultAccountInfo(
|
||||
ns, &scope, ImportedWatchonlyAddrAccount, nil, nil, 0, 0,
|
||||
ImportedWatchonlyAddrAccountName,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create creates a new address manager in the given namespace.
|
||||
|
|
|
@ -206,6 +206,13 @@ var (
|
|||
ImportedDerivationPath = DerivationPath{
|
||||
InternalAccount: ImportedAddrAccount,
|
||||
}
|
||||
|
||||
// ImportedWatchonlyDerivationPath is the derivation path for an
|
||||
// imported address. The Account, Branch, and Index members are not
|
||||
// known, so they are left blank.
|
||||
ImportedWatchonlyDerivationPath = DerivationPath{
|
||||
InternalAccount: ImportedWatchonlyAddrAccount,
|
||||
}
|
||||
)
|
||||
|
||||
// ScopedKeyManager is a sub key manager under the main root key manager. The
|
||||
|
@ -529,17 +536,47 @@ func (s *ScopedKeyManager) AccountProperties(ns walletdb.ReadBucket,
|
|||
}
|
||||
|
||||
// Until keys can be imported into any account, special handling is
|
||||
// required for the imported account.
|
||||
// required for the imported accounts.
|
||||
//
|
||||
// loadAccountInfo errors when using it on the imported account since
|
||||
// the accountInfo struct is filled with a BIP0044 account's extended
|
||||
// keys, and the imported accounts has none.
|
||||
//
|
||||
// Since only the imported account allows imports currently, the number
|
||||
// Since only the imported accounts allow imports currently, the number
|
||||
// of imported keys for any other account is zero, and since the
|
||||
// imported account cannot contain non-imported keys, the external and
|
||||
// internal key counts for it are zero.
|
||||
if account != ImportedAddrAccount {
|
||||
if account == ImportedAddrAccount {
|
||||
props.AccountName = ImportedAddrAccountName // reserved, nonchangable
|
||||
props.IsWatchOnly = false
|
||||
|
||||
// Could be more efficient if this was tracked by the db.
|
||||
var importedKeyCount uint32
|
||||
count := func(interface{}) error {
|
||||
importedKeyCount++
|
||||
return nil
|
||||
}
|
||||
err := forEachAccountAddress(ns, &s.scope, ImportedAddrAccount, count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
props.ImportedKeyCount = importedKeyCount
|
||||
} else if account == ImportedWatchonlyAddrAccount {
|
||||
props.AccountName = ImportedWatchonlyAddrAccountName // reserved, nonchangable
|
||||
props.IsWatchOnly = true
|
||||
|
||||
// Could be more efficient if this was tracked by the db.
|
||||
var importedKeyCount uint32
|
||||
count := func(interface{}) error {
|
||||
importedKeyCount++
|
||||
return nil
|
||||
}
|
||||
err := forEachAccountAddress(ns, &s.scope, ImportedWatchonlyAddrAccount, count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
props.ImportedKeyCount = importedKeyCount
|
||||
} else {
|
||||
acctInfo, err := s.loadAccountInfo(ns, account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -575,21 +612,6 @@ func (s *ScopedKeyManager) AccountProperties(ns walletdb.ReadBucket,
|
|||
"account public key: %v", err)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
props.AccountName = ImportedAddrAccountName // reserved, nonchangable
|
||||
props.IsWatchOnly = s.rootManager.WatchOnly()
|
||||
|
||||
// Could be more efficient if this was tracked by the db.
|
||||
var importedKeyCount uint32
|
||||
count := func(interface{}) error {
|
||||
importedKeyCount++
|
||||
return nil
|
||||
}
|
||||
err := forEachAccountAddress(ns, &s.scope, ImportedAddrAccount, count)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
props.ImportedKeyCount = importedKeyCount
|
||||
}
|
||||
|
||||
return props, nil
|
||||
|
|
|
@ -2457,8 +2457,8 @@ func (w *Wallet) AccountBalances(scope waddrmgr.KeyScope,
|
|||
results[i].AccountNumber = uint32(i)
|
||||
results[i].AccountName = accountName
|
||||
}
|
||||
results[len(results)-2].AccountName = waddrmgr.ImportedAddrAccountName
|
||||
results[len(results)-1].AccountNumber = waddrmgr.ImportedAddrAccount
|
||||
results[len(results)-1].AccountName = waddrmgr.ImportedAddrAccountName
|
||||
|
||||
// Fetch all unspent outputs, and iterate over them tallying each
|
||||
// account's balance where the output script pays to an account address
|
||||
|
@ -2488,6 +2488,8 @@ func (w *Wallet) AccountBalances(scope waddrmgr.KeyScope,
|
|||
continue
|
||||
}
|
||||
switch {
|
||||
case outputAcct == waddrmgr.ImportedWatchonlyAddrAccount:
|
||||
results[len(results)-2].AccountBalance += output.Amount
|
||||
case outputAcct == waddrmgr.ImportedAddrAccount:
|
||||
results[len(results)-1].AccountBalance += output.Amount
|
||||
case outputAcct > lastAcct:
|
||||
|
@ -3080,6 +3082,9 @@ func (w *Wallet) TotalReceivedForAccounts(scope waddrmgr.KeyScope,
|
|||
}
|
||||
if err == nil {
|
||||
acctIndex := int(outputAcct)
|
||||
if outputAcct == waddrmgr.ImportedWatchonlyAddrAccount {
|
||||
acctIndex = len(results) - 2
|
||||
}
|
||||
if outputAcct == waddrmgr.ImportedAddrAccount {
|
||||
acctIndex = len(results) - 1
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue