Skip to content

Commit

Permalink
udb: return base dbAccountRow for fetchAccountInfo.
Browse files Browse the repository at this point in the history
This updates the fetchAccountInfo function signature
to return a base account row which allows returning  different account types other than a BIP0044
account row.
  • Loading branch information
dnldd committed Jul 13, 2019
1 parent fc417f2 commit d521335
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 73 deletions.
9 changes: 2 additions & 7 deletions wallet/udb/addressdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ func fetchAccountByName(ns walletdb.ReadBucket, name string) (uint32, error) {

// fetchAccountInfo loads information about the passed account from the
// database.
func fetchAccountInfo(ns walletdb.ReadBucket, account uint32, dbVersion uint32) (*dbBIP0044AccountRow, error) {
func fetchAccountInfo(ns walletdb.ReadBucket, account uint32) (*dbAccountRow, error) {
bucket := ns.NestedReadBucket(acctBucketName)

accountID := uint32ToBytes(account)
Expand All @@ -717,12 +717,7 @@ func fetchAccountInfo(ns walletdb.ReadBucket, account uint32, dbVersion uint32)
return nil, err
}

switch row.acctType {
case actBIP0044:
return deserializeBIP0044AccountRow(accountID, row, dbVersion)
}

return nil, errors.E(errors.IO, errors.Errorf("unknown account type %d", row.acctType))
return row, nil
}

// deleteAccountNameIndex deletes the given key from the account name index of the database.
Expand Down
188 changes: 142 additions & 46 deletions wallet/udb/addressmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,13 +424,26 @@ func (m *Manager) GetMasterPubkey(ns walletdb.ReadBucket, account uint32) (strin

// The account is either invalid or just wasn't cached, so attempt to
// load the information from the database.
row, err := fetchAccountInfo(ns, account, DBVersion)
row, err := fetchAccountInfo(ns, account)
if err != nil {
return "", err
}

var acctRow *dbBIP0044AccountRow
switch row.acctType {
case actBIP0044:
accountID := uint32ToBytes(account)
acctRow, err = deserializeBIP0044AccountRow(accountID, row, DBVersion)
if err != nil {
return "", errors.E(errors.IO, err)
}

default:
return "", errors.E(errors.IO, errors.Errorf("unknown account type %d", row.acctType))
}

// Use the crypto public key to decrypt the account public extended key.
serializedKeyPub, err := m.cryptoKeyPub.Decrypt(row.pubKeyEncrypted)
serializedKeyPub, err := m.cryptoKeyPub.Decrypt(acctRow.pubKeyEncrypted)
if err != nil {
return "", errors.E(errors.IO, err)
}
Expand All @@ -451,16 +464,29 @@ func (m *Manager) loadAccountInfo(ns walletdb.ReadBucket, account uint32) (*acco

// The account is either invalid or just wasn't cached, so attempt to
// load the information from the database.
row, err := fetchAccountInfo(ns, account, DBVersion)
row, err := fetchAccountInfo(ns, account)
if err != nil {
if errors.Is(errors.NotExist, err) {
return nil, err
}
return nil, errors.E(errors.NotExist, errors.Errorf("no account %d", account))
}

var acctRow *dbBIP0044AccountRow
switch row.acctType {
case actBIP0044:
accountID := uint32ToBytes(account)
acctRow, err = deserializeBIP0044AccountRow(accountID, row, DBVersion)
if err != nil {
return nil, errors.E(errors.IO, err)
}

default:
return nil, errors.E(errors.IO, errors.Errorf("unknown account type %d", row.acctType))
}

// Use the crypto public key to decrypt the account public extended key.
serializedKeyPub, err := m.cryptoKeyPub.Decrypt(row.pubKeyEncrypted)
serializedKeyPub, err := m.cryptoKeyPub.Decrypt(acctRow.pubKeyEncrypted)
if err != nil {
return nil, errors.E(errors.Crypto, errors.Errorf("decrypt account %d pubkey: %v", account, err))
}
Expand All @@ -472,8 +498,8 @@ func (m *Manager) loadAccountInfo(ns walletdb.ReadBucket, account uint32) (*acco
// Create the new account info with the known information. The rest
// of the fields are filled out below.
acctInfo := &accountInfo{
acctName: row.name,
acctKeyEncrypted: row.privKeyEncrypted,
acctName: acctRow.name,
acctKeyEncrypted: acctRow.privKeyEncrypted,
acctKeyPub: acctKeyPub,
}

Expand Down Expand Up @@ -527,14 +553,28 @@ func (m *Manager) AccountProperties(ns walletdb.ReadBucket, account uint32) (*Ac
return nil, err
}
props.AccountName = acctInfo.acctName
row, err := fetchAccountInfo(ns, account, DBVersion)
row, err := fetchAccountInfo(ns, account)
if err != nil {
return nil, errors.E(errors.IO, err)
}
props.LastUsedExternalIndex = row.lastUsedExternalIndex
props.LastUsedInternalIndex = row.lastUsedInternalIndex
props.LastReturnedExternalIndex = row.lastReturnedExternalIndex
props.LastReturnedInternalIndex = row.lastReturnedInternalIndex

var acctRow *dbBIP0044AccountRow
switch row.acctType {
case actBIP0044:
accountID := uint32ToBytes(account)
acctRow, err = deserializeBIP0044AccountRow(accountID, row, DBVersion)
if err != nil {
return nil, errors.E(errors.IO, err)
}

default:
return nil, errors.E(errors.IO, errors.Errorf("unknown account type %d", row.acctType))
}

props.LastUsedExternalIndex = acctRow.lastUsedExternalIndex
props.LastUsedInternalIndex = acctRow.lastUsedInternalIndex
props.LastReturnedExternalIndex = acctRow.lastReturnedExternalIndex
props.LastReturnedInternalIndex = acctRow.lastReturnedInternalIndex
} else {
props.AccountName = ImportedAddrAccountName // reserved, nonchangable

Expand Down Expand Up @@ -1449,12 +1489,27 @@ func (m *Manager) MarkUsed(ns walletdb.ReadWriteBucket, address dcrutil.Address)
if !ok {
return nil
}
row, err := fetchAccountInfo(ns, bip0044Addr.account, DBVersion)

row, err := fetchAccountInfo(ns, bip0044Addr.account)
if err != nil {
return errors.E(errors.IO, errors.Errorf("missing account %d", bip0044Addr.account))
}
lastUsedExtIndex := row.lastUsedExternalIndex
lastUsedIntIndex := row.lastUsedInternalIndex

var acctRow *dbBIP0044AccountRow
switch row.acctType {
case actBIP0044:
accountID := uint32ToBytes(bip0044Addr.account)
acctRow, err = deserializeBIP0044AccountRow(accountID, row, DBVersion)
if err != nil {
return errors.E(errors.IO, err)
}

default:
return errors.E(errors.IO, errors.Errorf("unknown account type %d", row.acctType))
}

lastUsedExtIndex := acctRow.lastUsedExternalIndex
lastUsedIntIndex := acctRow.lastUsedInternalIndex
switch bip0044Addr.branch {
case ExternalBranch:
lastUsedExtIndex = bip0044Addr.index
Expand All @@ -1464,8 +1519,8 @@ func (m *Manager) MarkUsed(ns walletdb.ReadWriteBucket, address dcrutil.Address)
return errors.E(errors.IO, errors.Errorf("invalid account branch %d", bip0044Addr.branch))
}

if lastUsedExtIndex+1 < row.lastUsedExternalIndex+1 ||
lastUsedIntIndex+1 < row.lastUsedInternalIndex+1 {
if lastUsedExtIndex+1 < acctRow.lastUsedExternalIndex+1 ||
lastUsedIntIndex+1 < acctRow.lastUsedInternalIndex+1 {
// More recent addresses have already been marked used, nothing to
// update.
return nil
Expand All @@ -1474,25 +1529,39 @@ func (m *Manager) MarkUsed(ns walletdb.ReadWriteBucket, address dcrutil.Address)
// The last returned indexes should never be less than the last used. The
// weird addition and subtraction makes this calculation work correctly even
// when any of of the indexes are ^uint32(0).
lastRetExtIndex := maxUint32(lastUsedExtIndex+1, row.lastReturnedExternalIndex+1) - 1
lastRetIntIndex := maxUint32(lastUsedIntIndex+1, row.lastReturnedInternalIndex+1) - 1
lastRetExtIndex := maxUint32(lastUsedExtIndex+1, acctRow.lastReturnedExternalIndex+1) - 1
lastRetIntIndex := maxUint32(lastUsedIntIndex+1, acctRow.lastReturnedInternalIndex+1) - 1

row = bip0044AccountInfo(row.pubKeyEncrypted, row.privKeyEncrypted, 0, 0,
acctRow = bip0044AccountInfo(acctRow.pubKeyEncrypted, acctRow.privKeyEncrypted, 0, 0,
lastUsedExtIndex, lastUsedIntIndex, lastRetExtIndex, lastRetIntIndex,
row.name, DBVersion)
return putAccountRow(ns, bip0044Addr.account, &row.dbAccountRow)
acctRow.name, DBVersion)
return putAccountRow(ns, bip0044Addr.account, &acctRow.dbAccountRow)
}

// MarkUsedChildIndex marks a BIP0044 account branch child as used.
func (m *Manager) MarkUsedChildIndex(tx walletdb.ReadWriteTx, account, branch, child uint32) error {
ns := tx.ReadWriteBucket(waddrmgrBucketKey)

row, err := fetchAccountInfo(ns, account, DBVersion)
row, err := fetchAccountInfo(ns, account)
if err != nil {
return err
}
lastUsedExtIndex := row.lastUsedExternalIndex
lastUsedIntIndex := row.lastUsedInternalIndex

var acctRow *dbBIP0044AccountRow
switch row.acctType {
case actBIP0044:
accountID := uint32ToBytes(account)
acctRow, err = deserializeBIP0044AccountRow(accountID, row, DBVersion)
if err != nil {
return errors.E(errors.IO, err)
}

default:
return errors.E(errors.IO, errors.Errorf("unknown account type %d", row.acctType))
}

lastUsedExtIndex := acctRow.lastUsedExternalIndex
lastUsedIntIndex := acctRow.lastUsedInternalIndex
switch branch {
case ExternalBranch:
lastUsedExtIndex = child
Expand All @@ -1502,8 +1571,8 @@ func (m *Manager) MarkUsedChildIndex(tx walletdb.ReadWriteTx, account, branch, c
return errors.E(errors.Invalid, errors.Errorf("account branch %d", branch))
}

if lastUsedExtIndex+1 < row.lastUsedExternalIndex+1 ||
lastUsedIntIndex+1 < row.lastUsedInternalIndex+1 {
if lastUsedExtIndex+1 < acctRow.lastUsedExternalIndex+1 ||
lastUsedIntIndex+1 < acctRow.lastUsedInternalIndex+1 {
// More recent addresses have already been marked used, nothing to
// update.
return nil
Expand All @@ -1512,13 +1581,13 @@ func (m *Manager) MarkUsedChildIndex(tx walletdb.ReadWriteTx, account, branch, c
// The last returned indexes should never be less than the last used. The
// weird addition and subtraction makes this calculation work correctly even
// when any of of the indexes are ^uint32(0).
lastRetExtIndex := maxUint32(lastUsedExtIndex+1, row.lastReturnedExternalIndex+1) - 1
lastRetIntIndex := maxUint32(lastUsedIntIndex+1, row.lastReturnedInternalIndex+1) - 1
lastRetExtIndex := maxUint32(lastUsedExtIndex+1, acctRow.lastReturnedExternalIndex+1) - 1
lastRetIntIndex := maxUint32(lastUsedIntIndex+1, acctRow.lastReturnedInternalIndex+1) - 1

row = bip0044AccountInfo(row.pubKeyEncrypted, row.privKeyEncrypted, 0, 0,
acctRow = bip0044AccountInfo(acctRow.pubKeyEncrypted, acctRow.privKeyEncrypted, 0, 0,
lastUsedExtIndex, lastUsedIntIndex, lastRetExtIndex, lastRetIntIndex,
row.name, DBVersion)
return putAccountRow(ns, account, &row.dbAccountRow)
acctRow.name, DBVersion)
return putAccountRow(ns, account, &acctRow.dbAccountRow)
}

// MarkReturnedChildIndex marks a BIP0044 account branch child as returned to a
Expand All @@ -1528,12 +1597,26 @@ func (m *Manager) MarkUsedChildIndex(tx walletdb.ReadWriteTx, account, branch, c
func (m *Manager) MarkReturnedChildIndex(tx walletdb.ReadWriteTx, account, branch, child uint32) error {
ns := tx.ReadWriteBucket(waddrmgrBucketKey)

row, err := fetchAccountInfo(ns, account, DBVersion)
row, err := fetchAccountInfo(ns, account)
if err != nil {
return err
}
lastRetExtIndex := row.lastReturnedExternalIndex
lastRetIntIndex := row.lastReturnedInternalIndex

var acctRow *dbBIP0044AccountRow
switch row.acctType {
case actBIP0044:
accountID := uint32ToBytes(account)
acctRow, err = deserializeBIP0044AccountRow(accountID, row, DBVersion)
if err != nil {
return errors.E(errors.IO, err)
}

default:
return errors.E(errors.IO, errors.Errorf("unknown account type %d", row.acctType))
}

lastRetExtIndex := acctRow.lastReturnedExternalIndex
lastRetIntIndex := acctRow.lastReturnedInternalIndex
switch branch {
case ExternalBranch:
lastRetExtIndex = child
Expand All @@ -1546,13 +1629,13 @@ func (m *Manager) MarkReturnedChildIndex(tx walletdb.ReadWriteTx, account, branc
// The last returned indexes should never be less than the last used. The
// weird addition and subtraction makes this calculation work correctly even
// when any of of the indexes are ^uint32(0).
lastRetExtIndex = maxUint32(row.lastUsedExternalIndex+1, lastRetExtIndex+1) - 1
lastRetIntIndex = maxUint32(row.lastUsedInternalIndex+1, lastRetIntIndex+1) - 1
lastRetExtIndex = maxUint32(acctRow.lastUsedExternalIndex+1, lastRetExtIndex+1) - 1
lastRetIntIndex = maxUint32(acctRow.lastUsedInternalIndex+1, lastRetIntIndex+1) - 1

row = bip0044AccountInfo(row.pubKeyEncrypted, row.privKeyEncrypted, 0, 0,
row.lastUsedExternalIndex, row.lastUsedInternalIndex,
lastRetExtIndex, lastRetIntIndex, row.name, DBVersion)
return putAccountRow(ns, account, &row.dbAccountRow)
acctRow = bip0044AccountInfo(acctRow.pubKeyEncrypted, acctRow.privKeyEncrypted, 0, 0,
acctRow.lastUsedExternalIndex, acctRow.lastUsedInternalIndex,
lastRetExtIndex, lastRetIntIndex, acctRow.name, DBVersion)
return putAccountRow(ns, account, &acctRow.dbAccountRow)
}

// ChainParams returns the chain parameters for this address manager.
Expand Down Expand Up @@ -1789,24 +1872,37 @@ func (m *Manager) RenameAccount(ns walletdb.ReadWriteBucket, account uint32, nam
return err
}

row, err := fetchAccountInfo(ns, account, DBVersion)
row, err := fetchAccountInfo(ns, account)
if err != nil {
return err
}

var acctRow *dbBIP0044AccountRow
switch row.acctType {
case actBIP0044:
accountID := uint32ToBytes(account)
acctRow, err = deserializeBIP0044AccountRow(accountID, row, DBVersion)
if err != nil {
return errors.E(errors.IO, err)
}

default:
return errors.E(errors.IO, errors.Errorf("unknown account type %d", row.acctType))
}

// Remove the old name key from the accout id index
if err = deleteAccountIDIndex(ns, account); err != nil {
return err
}
// Remove the old name key from the account name index
if err = deleteAccountNameIndex(ns, row.name); err != nil {
if err = deleteAccountNameIndex(ns, acctRow.name); err != nil {
return err
}
row = bip0044AccountInfo(row.pubKeyEncrypted, row.privKeyEncrypted,
0, 0, row.lastUsedExternalIndex, row.lastUsedInternalIndex,
row.lastReturnedExternalIndex, row.lastReturnedInternalIndex,
acctRow = bip0044AccountInfo(acctRow.pubKeyEncrypted, acctRow.privKeyEncrypted,
0, 0, acctRow.lastUsedExternalIndex, acctRow.lastUsedInternalIndex,
acctRow.lastReturnedExternalIndex, acctRow.lastReturnedInternalIndex,
name, DBVersion)
err = putAccountInfo(ns, account, row)
err = putAccountInfo(ns, account, acctRow)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit d521335

Please sign in to comment.