Add func to get next n active addresses.

This adds a new function, ExtendActiveAddresses, to extend the number
of active addresses, generated by the address chain, by any arbitrary
positive number.  This will be used for recovering wallet addresses
from a wallet backup, as well as getting the next as many addresses as
required to keep a watching wallet in sync with an original wallet
with the private keys, or sync an original wallet with new addresses
generated by the watching wallet.
This commit is contained in:
Josh Rickmar 2014-01-21 11:19:08 -05:00
parent effd810e54
commit 04b51ee426
2 changed files with 73 additions and 0 deletions

View file

@ -1376,6 +1376,33 @@ func (w *Wallet) ActiveAddresses() map[btcutil.Address]*AddressInfo {
return addrs
}
// ExtendActiveAddresses gets or creates the next n addresses from the
// address chain and marks each as active. This is used to recover
// deterministic (not imported) addresses from a wallet backup, or to
// keep the active addresses in sync between an encrypted wallet with
// private keys and an exported watching wallet without.
//
// A slice is returned with the btcutil.Address of each new address.
// The blockchain must be rescanned for these addresses.
func (w *Wallet) ExtendActiveAddresses(n int, keypoolSize uint) ([]btcutil.Address, error) {
if n <= 0 {
return nil, errors.New("n is not positive")
}
last := w.addrMap[*w.chainIdxMap[w.highestUsed]]
bs := &BlockStamp{Height: last.firstBlock}
addrs := make([]btcutil.Address, 0, n)
for i := 0; i < n; i++ {
addr, err := w.NextChainedAddress(bs, keypoolSize)
if err != nil {
return nil, err
}
addrs = append(addrs, addr)
}
return addrs, nil
}
type walletFlags struct {
useEncryption bool
watchingOnly bool

View file

@ -579,6 +579,52 @@ func TestWatchingWalletExport(t *testing.T) {
}
}
// Test that ExtendActiveAddresses for the watching wallet match
// manually requested addresses of the original wallet.
newAddrs := make([]btcutil.Address, 0, keypoolSize)
for i := 0; i < keypoolSize; i++ {
addr, err := w.NextChainedAddress(createdAt, keypoolSize)
if err != nil {
t.Errorf("Cannot get next chained address for original wallet: %v", err)
return
}
newAddrs = append(newAddrs, addr)
}
newWWAddrs, err := ww.ExtendActiveAddresses(keypoolSize, keypoolSize)
if err != nil {
t.Errorf("Cannot extend active addresses for watching wallet: %v", err)
return
}
for i := range newAddrs {
if newAddrs[i].EncodeAddress() != newWWAddrs[i].EncodeAddress() {
t.Errorf("Extended active addresses do not match manually requested addresses.")
return
}
}
// Test ExtendActiveAddresses for the original wallet after manually
// requesting addresses for the watching wallet.
newWWAddrs = make([]btcutil.Address, 0, keypoolSize)
for i := 0; i < keypoolSize; i++ {
addr, err := ww.NextChainedAddress(createdAt, keypoolSize)
if err != nil {
t.Errorf("Cannot get next chained address for watching wallet: %v", err)
return
}
newWWAddrs = append(newWWAddrs, addr)
}
newAddrs, err = w.ExtendActiveAddresses(keypoolSize, keypoolSize)
if err != nil {
t.Errorf("Cannot extend active addresses for original wallet: %v", err)
return
}
for i := range newAddrs {
if newAddrs[i].EncodeAddress() != newWWAddrs[i].EncodeAddress() {
t.Errorf("Extended active addresses do not match manually requested addresses.")
return
}
}
// Test (de)serialization of watching wallet.
buf := new(bytes.Buffer)
_, err = ww.WriteTo(buf)