Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix panic in getaddressesbyaccount. #678

Merged
merged 1 commit into from Apr 24, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 10 additions & 10 deletions rpc/legacyrpc/methods.go
Expand Up @@ -319,7 +319,7 @@ func jsonError(err error) *dcrjson.RPCError {
}
}

// accountAddressIndex returns the current address index for the passed
// accountAddressIndex returns the next address index for the passed
// account and branch.
func accountAddressIndex(icmd interface{}, w *wallet.Wallet) (interface{}, error) {
cmd := icmd.(*dcrjson.AccountAddressIndexCmd)
Expand All @@ -328,7 +328,7 @@ func accountAddressIndex(icmd interface{}, w *wallet.Wallet) (interface{}, error
return nil, err
}

extChild, intChild, err := w.BIP0044BranchIndexes(account)
extChild, intChild, err := w.BIP0044BranchNextIndexes(account)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -365,8 +365,10 @@ func accountFetchAddresses(icmd interface{}, w *wallet.Wallet) (interface{}, err
cmd.End)
}

addrs, err := w.AccountBranchAddressRange(uint32(cmd.Start),
uint32(cmd.End), account, branch)
// AccountBranchAddressRange uses the range [start, end) but the RPC for
// some reason uses (start, end], so add to each index.
addrs, err := w.AccountBranchAddressRange(account, branch, uint32(cmd.Start)+1,
uint32(cmd.End)+1)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -634,8 +636,8 @@ func getAddressesByAccount(icmd interface{}, w *wallet.Wallet) (interface{}, err
return nil, err
}

// Find the current synced-to indexes from the address pool.
endExt, endInt, err := w.BIP0044BranchIndexes(account)
// Find the next child address indexes for the account.
endExt, endInt, err := w.BIP0044BranchNextIndexes(account)
if err != nil {
return nil, err
}
Expand All @@ -647,16 +649,14 @@ func getAddressesByAccount(icmd interface{}, w *wallet.Wallet) (interface{}, err

// Derive the addresses.
addrsStr := make([]string, endInt+endExt)
addrsExt, err := w.AccountBranchAddressRange(0, endExt,
account, udb.ExternalBranch)
addrsExt, err := w.AccountBranchAddressRange(account, udb.ExternalBranch, 0, endExt)
if err != nil {
return nil, err
}
for i := range addrsExt {
addrsStr[i] = addrsExt[i].EncodeAddress()
}
addrsInt, err := w.AccountBranchAddressRange(0, endInt,
account, udb.InternalBranch)
addrsInt, err := w.AccountBranchAddressRange(account, udb.InternalBranch, 0, endInt)
if err != nil {
return nil, err
}
Expand Down
38 changes: 34 additions & 4 deletions wallet/addresses.go
Expand Up @@ -262,9 +262,9 @@ func (w *Wallet) NewInternalAddress(account uint32) (dcrutil.Address, error) {
return w.nextAddress(account, udb.InternalBranch)
}

// BIP0044BranchIndexes returns the current external and internal branch child
// BIP0044BranchNextIndexes returns the next external and internal branch child
// indexes of an account.
func (w *Wallet) BIP0044BranchIndexes(account uint32) (extChild, intChild uint32, err error) {
func (w *Wallet) BIP0044BranchNextIndexes(account uint32) (extChild, intChild uint32, err error) {
defer w.addressBuffersMu.Unlock()
w.addressBuffersMu.Lock()

Expand All @@ -273,8 +273,8 @@ func (w *Wallet) BIP0044BranchIndexes(account uint32) (extChild, intChild uint32
const str = "account not found"
return 0, 0, apperrors.E{ErrorCode: apperrors.ErrAccountNotFound, Description: str, Err: nil}
}
extChild = acctData.albExternal.lastUsed + acctData.albExternal.cursor
intChild = acctData.albInternal.lastUsed + acctData.albInternal.cursor
extChild = acctData.albExternal.lastUsed + 1 + acctData.albExternal.cursor
intChild = acctData.albInternal.lastUsed + 1 + acctData.albInternal.cursor
return extChild, intChild, nil
}

Expand Down Expand Up @@ -341,6 +341,36 @@ func (w *Wallet) ExtendWatchedAddresses(account, branch, child uint32) error {
return nil
}

// AccountBranchAddressRange returns all addresses in the range [start, end)
// belonging to the BIP0044 account and address branch.
func (w *Wallet) AccountBranchAddressRange(account, branch, start, end uint32) ([]dcrutil.Address, error) {
if end < start {
const str = "end index must not be less than start index"
return nil, apperrors.E{ErrorCode: apperrors.ErrInput, Description: str, Err: nil}
}

defer w.addressBuffersMu.Unlock()
w.addressBuffersMu.Lock()

acctBufs, ok := w.addressBuffers[account]
if !ok {
const str = "account not found"
return nil, apperrors.E{ErrorCode: apperrors.ErrAccountNotFound, Description: str, Err: nil}
}

var buf *addressBuffer
switch branch {
case udb.ExternalBranch:
buf = &acctBufs.albExternal
case udb.InternalBranch:
buf = &acctBufs.albInternal
default:
const str = "unknown branch"
return nil, apperrors.E{ErrorCode: apperrors.ErrBranch, Description: str, Err: nil}
}
return deriveChildAddresses(buf.branchXpub, start, end-start, w.chainParams)
}

func (w *Wallet) changeSource(account uint32) txauthor.ChangeSource {
return func() ([]byte, uint16, error) {
changeAddress, err := w.changeAddress(account)
Expand Down
26 changes: 0 additions & 26 deletions wallet/wallet.go
Expand Up @@ -1611,32 +1611,6 @@ func (w *Wallet) CurrentAddress(account uint32) (dcrutil.Address, error) {
return child.Address(w.chainParams)
}

// AccountBranchAddressRange returns all addresses in the left-open,
// right-closed range (start, end] belonging to the BIP0044 account and address
// branch.
func (w *Wallet) AccountBranchAddressRange(start, end uint32, account uint32, branch uint32) ([]dcrutil.Address, error) {
defer w.addressBuffersMu.Unlock()
w.addressBuffersMu.Lock()

acctBufs, ok := w.addressBuffers[account]
if !ok {
const str = "account not found"
return nil, apperrors.E{ErrorCode: apperrors.ErrAccountNotFound, Description: str, Err: nil}
}

var buf *addressBuffer
switch branch {
case udb.ExternalBranch:
buf = &acctBufs.albExternal
case udb.InternalBranch:
buf = &acctBufs.albInternal
default:
const str = "unknown branch"
return nil, apperrors.E{ErrorCode: apperrors.ErrBranch, Description: str, Err: nil}
}
return deriveChildAddresses(buf.branchXpub, start+1, end-start+1, w.chainParams)
}

// PubKeyForAddress looks up the associated public key for a P2PKH address.
func (w *Wallet) PubKeyForAddress(a dcrutil.Address) (chainec.PublicKey, error) {
var pubKey chainec.PublicKey
Expand Down