consolidate: merge internal/external branches
This commit is contained in:
parent
de408d4133
commit
0410b7ce01
10 changed files with 132 additions and 321 deletions
|
@ -31,26 +31,18 @@ type BlockFilterer struct {
|
|||
// Params specifies the chain params of the current network.
|
||||
Params *chaincfg.Params
|
||||
|
||||
// ExReverseFilter holds a reverse index mapping an external address to
|
||||
// ReverseFilter holds a reverse index mapping an external address to
|
||||
// the scoped index from which it was derived.
|
||||
ExReverseFilter map[string]waddrmgr.ScopedIndex
|
||||
|
||||
// InReverseFilter holds a reverse index mapping an internal address to
|
||||
// the scoped index from which it was derived.
|
||||
InReverseFilter map[string]waddrmgr.ScopedIndex
|
||||
ReverseFilter map[string]waddrmgr.ScopedIndex
|
||||
|
||||
// WathcedOutPoints is a global set of outpoints being tracked by the
|
||||
// wallet. This allows the block filterer to check for spends from an
|
||||
// outpoint we own.
|
||||
WatchedOutPoints map[wire.OutPoint]btcutil.Address
|
||||
|
||||
// FoundExternal is a two-layer map recording the scope and index of
|
||||
// FoundAddresses is a two-layer map recording the scope and index of
|
||||
// external addresses found in a single block.
|
||||
FoundExternal map[waddrmgr.KeyScope]map[uint32]struct{}
|
||||
|
||||
// FoundInternal is a two-layer map recording the scope and index of
|
||||
// internal addresses found in a single block.
|
||||
FoundInternal map[waddrmgr.KeyScope]map[uint32]struct{}
|
||||
FoundAddresses map[waddrmgr.ScopedIndex]struct{}
|
||||
|
||||
// FoundOutPoints is a set of outpoints found in a single block whose
|
||||
// address belongs to the wallet.
|
||||
|
@ -71,31 +63,20 @@ func NewBlockFilterer(params *chaincfg.Params,
|
|||
|
||||
// Construct a reverse index by address string for the requested
|
||||
// external addresses.
|
||||
nExAddrs := len(req.ExternalAddrs)
|
||||
exReverseFilter := make(map[string]waddrmgr.ScopedIndex, nExAddrs)
|
||||
for scopedIndex, addr := range req.ExternalAddrs {
|
||||
exReverseFilter[addr.EncodeAddress()] = scopedIndex
|
||||
nAddrs := len(req.Addresses)
|
||||
reverseFilter := make(map[string]waddrmgr.ScopedIndex, nAddrs)
|
||||
for scopedIndex, addr := range req.Addresses {
|
||||
reverseFilter[addr.EncodeAddress()] = scopedIndex
|
||||
}
|
||||
|
||||
// Construct a reverse index by address string for the requested
|
||||
// internal addresses.
|
||||
nInAddrs := len(req.InternalAddrs)
|
||||
inReverseFilter := make(map[string]waddrmgr.ScopedIndex, nInAddrs)
|
||||
for scopedIndex, addr := range req.InternalAddrs {
|
||||
inReverseFilter[addr.EncodeAddress()] = scopedIndex
|
||||
}
|
||||
|
||||
foundExternal := make(map[waddrmgr.KeyScope]map[uint32]struct{})
|
||||
foundInternal := make(map[waddrmgr.KeyScope]map[uint32]struct{})
|
||||
foundAddresses := make(map[waddrmgr.ScopedIndex]struct{})
|
||||
foundOutPoints := make(map[wire.OutPoint]btcutil.Address)
|
||||
|
||||
return &BlockFilterer{
|
||||
Params: params,
|
||||
ExReverseFilter: exReverseFilter,
|
||||
InReverseFilter: inReverseFilter,
|
||||
ReverseFilter: reverseFilter,
|
||||
WatchedOutPoints: req.WatchedOutPoints,
|
||||
FoundExternal: foundExternal,
|
||||
FoundInternal: foundInternal,
|
||||
FoundAddresses: foundAddresses,
|
||||
FoundOutPoints: foundOutPoints,
|
||||
}
|
||||
}
|
||||
|
@ -183,12 +164,8 @@ func (bf *BlockFilterer) FilterOutputAddrs(addrs []btcutil.Address) bool {
|
|||
var isRelevant bool
|
||||
for _, addr := range addrs {
|
||||
addrStr := addr.EncodeAddress()
|
||||
if scopedIndex, ok := bf.ExReverseFilter[addrStr]; ok {
|
||||
bf.foundExternal(scopedIndex)
|
||||
isRelevant = true
|
||||
}
|
||||
if scopedIndex, ok := bf.InReverseFilter[addrStr]; ok {
|
||||
bf.foundInternal(scopedIndex)
|
||||
if scopedIndex, ok := bf.ReverseFilter[addrStr]; ok {
|
||||
bf.found(scopedIndex)
|
||||
isRelevant = true
|
||||
}
|
||||
}
|
||||
|
@ -196,22 +173,9 @@ func (bf *BlockFilterer) FilterOutputAddrs(addrs []btcutil.Address) bool {
|
|||
return isRelevant
|
||||
}
|
||||
|
||||
// foundExternal marks the scoped index as found within the block filterer's
|
||||
// found marks the scoped index as found within the block filterer's
|
||||
// FoundExternal map. If this the first index found for a particular scope, the
|
||||
// scope's second layer map will be initialized before marking the index.
|
||||
func (bf *BlockFilterer) foundExternal(scopedIndex waddrmgr.ScopedIndex) {
|
||||
if _, ok := bf.FoundExternal[scopedIndex.Scope]; !ok {
|
||||
bf.FoundExternal[scopedIndex.Scope] = make(map[uint32]struct{})
|
||||
}
|
||||
bf.FoundExternal[scopedIndex.Scope][scopedIndex.Index] = struct{}{}
|
||||
}
|
||||
|
||||
// foundInternal marks the scoped index as found within the block filterer's
|
||||
// FoundInternal map. If this the first index found for a particular scope, the
|
||||
// scope's second layer map will be initialized before marking the index.
|
||||
func (bf *BlockFilterer) foundInternal(scopedIndex waddrmgr.ScopedIndex) {
|
||||
if _, ok := bf.FoundInternal[scopedIndex.Scope]; !ok {
|
||||
bf.FoundInternal[scopedIndex.Scope] = make(map[uint32]struct{})
|
||||
}
|
||||
bf.FoundInternal[scopedIndex.Scope][scopedIndex.Index] = struct{}{}
|
||||
func (bf *BlockFilterer) found(scopedIndex waddrmgr.ScopedIndex) {
|
||||
bf.FoundAddresses[scopedIndex] = struct{}{}
|
||||
}
|
||||
|
|
|
@ -75,8 +75,7 @@ type (
|
|||
// is also included to monitor for spends.
|
||||
FilterBlocksRequest struct {
|
||||
Blocks []wtxmgr.BlockMeta
|
||||
ExternalAddrs map[waddrmgr.ScopedIndex]btcutil.Address
|
||||
InternalAddrs map[waddrmgr.ScopedIndex]btcutil.Address
|
||||
Addresses map[waddrmgr.ScopedIndex]btcutil.Address
|
||||
WatchedOutPoints map[wire.OutPoint]btcutil.Address
|
||||
}
|
||||
|
||||
|
@ -90,8 +89,7 @@ type (
|
|||
FilterBlocksResponse struct {
|
||||
BatchIndex uint32
|
||||
BlockMeta wtxmgr.BlockMeta
|
||||
FoundExternalAddrs map[waddrmgr.KeyScope]map[uint32]struct{}
|
||||
FoundInternalAddrs map[waddrmgr.KeyScope]map[uint32]struct{}
|
||||
FoundAddresses map[waddrmgr.ScopedIndex]struct{}
|
||||
FoundOutPoints map[wire.OutPoint]btcutil.Address
|
||||
RelevantTxns []*wire.MsgTx
|
||||
}
|
||||
|
|
|
@ -12,22 +12,12 @@ func buildFilterBlocksWatchList(req *FilterBlocksRequest) ([][]byte, error) {
|
|||
// Construct a watch list containing the script addresses of all
|
||||
// internal and external addresses that were requested, in addition to
|
||||
// the set of outpoints currently being watched.
|
||||
watchListSize := len(req.ExternalAddrs) +
|
||||
len(req.InternalAddrs) +
|
||||
watchListSize := len(req.Addresses) +
|
||||
len(req.WatchedOutPoints)
|
||||
|
||||
watchList := make([][]byte, 0, watchListSize)
|
||||
|
||||
for _, addr := range req.ExternalAddrs {
|
||||
p2shAddr, err := txscript.PayToAddrScript(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
watchList = append(watchList, p2shAddr)
|
||||
}
|
||||
|
||||
for _, addr := range req.InternalAddrs {
|
||||
for _, addr := range req.Addresses {
|
||||
p2shAddr, err := txscript.PayToAddrScript(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -272,8 +272,7 @@ func (c *RPCClient) FilterBlocks(
|
|||
resp := &FilterBlocksResponse{
|
||||
BatchIndex: uint32(i),
|
||||
BlockMeta: blk,
|
||||
FoundExternalAddrs: blockFilterer.FoundExternal,
|
||||
FoundInternalAddrs: blockFilterer.FoundInternal,
|
||||
FoundAddresses: blockFilterer.FoundAddresses,
|
||||
FoundOutPoints: blockFilterer.FoundOutPoints,
|
||||
RelevantTxns: blockFilterer.RelevantTxns,
|
||||
}
|
||||
|
|
|
@ -156,13 +156,8 @@ type accountInfo struct {
|
|||
|
||||
// The external branch is used for all addresses which are intended for
|
||||
// external use.
|
||||
nextExternalIndex uint32
|
||||
lastExternalAddr ManagedAddress
|
||||
|
||||
// The internal branch is used for all adddresses which are only
|
||||
// intended for internal wallet use such as change addresses.
|
||||
nextInternalIndex uint32
|
||||
lastInternalAddr ManagedAddress
|
||||
nextIndex [2]uint32
|
||||
lastAddr [2]ManagedAddress
|
||||
|
||||
// addrSchema serves as a way for an account to override its
|
||||
// corresponding address schema with a custom one.
|
||||
|
|
|
@ -334,8 +334,8 @@ func testExternalAddresses(tc *testContext) bool {
|
|||
err := walletdb.Update(tc.db, func(tx walletdb.ReadWriteTx) error {
|
||||
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
var err error
|
||||
addrs, err = tc.manager.NextExternalAddresses(
|
||||
ns, tc.internalAccount, 5,
|
||||
addrs, err = tc.manager.NextAddresses(
|
||||
ns, tc.internalAccount, ExternalBranch, 5,
|
||||
)
|
||||
return err
|
||||
})
|
||||
|
@ -371,8 +371,8 @@ func testExternalAddresses(tc *testContext) bool {
|
|||
err := walletdb.View(tc.db, func(tx walletdb.ReadTx) error {
|
||||
ns := tx.ReadBucket(waddrmgrNamespaceKey)
|
||||
var err error
|
||||
lastAddr, err = tc.manager.LastExternalAddress(
|
||||
ns, tc.internalAccount,
|
||||
lastAddr, err = tc.manager.LastAddress(
|
||||
ns, tc.internalAccount, ExternalBranch,
|
||||
)
|
||||
return err
|
||||
})
|
||||
|
@ -478,8 +478,8 @@ func testInternalAddresses(tc *testContext) bool {
|
|||
err := walletdb.Update(tc.db, func(tx walletdb.ReadWriteTx) error {
|
||||
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
var err error
|
||||
addrs, err = tc.manager.NextInternalAddresses(
|
||||
ns, tc.internalAccount, 5,
|
||||
addrs, err = tc.manager.NextAddresses(
|
||||
ns, tc.internalAccount, InternalBranch, 5,
|
||||
)
|
||||
return err
|
||||
})
|
||||
|
@ -515,8 +515,8 @@ func testInternalAddresses(tc *testContext) bool {
|
|||
err := walletdb.View(tc.db, func(tx walletdb.ReadTx) error {
|
||||
ns := tx.ReadBucket(waddrmgrNamespaceKey)
|
||||
var err error
|
||||
lastAddr, err = tc.manager.LastInternalAddress(
|
||||
ns, tc.internalAccount,
|
||||
lastAddr, err = tc.manager.LastAddress(
|
||||
ns, tc.internalAccount, InternalBranch,
|
||||
)
|
||||
return err
|
||||
})
|
||||
|
@ -2032,8 +2032,8 @@ func TestScopedKeyManagerManagement(t *testing.T) {
|
|||
t.Fatalf("unable to fetch scope %v: %v", scope, err)
|
||||
}
|
||||
|
||||
externalAddr, err := sMgr.NextExternalAddresses(
|
||||
ns, DefaultAccountNum, 1,
|
||||
externalAddr, err := sMgr.NextAddresses(
|
||||
ns, DefaultAccountNum, ExternalBranch, 1,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to derive external addr: %v", err)
|
||||
|
@ -2047,8 +2047,8 @@ func TestScopedKeyManagerManagement(t *testing.T) {
|
|||
ScopeAddrMap[scope].ExternalAddrType)
|
||||
}
|
||||
|
||||
internalAddr, err := sMgr.NextInternalAddresses(
|
||||
ns, DefaultAccountNum, 1,
|
||||
internalAddr, err := sMgr.NextAddresses(
|
||||
ns, DefaultAccountNum, InternalBranch, 1,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to derive internal addr: %v", err)
|
||||
|
@ -2106,15 +2106,15 @@ func TestScopedKeyManagerManagement(t *testing.T) {
|
|||
|
||||
// We'll now create a new external address to ensure we
|
||||
// retrieve the proper type.
|
||||
externalAddr, err = scopedMgr.NextExternalAddresses(
|
||||
ns, DefaultAccountNum, 1,
|
||||
externalAddr, err = scopedMgr.NextAddresses(
|
||||
ns, DefaultAccountNum, ExternalBranch, 1,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to derive external addr: %v", err)
|
||||
}
|
||||
|
||||
internalAddr, err = scopedMgr.NextInternalAddresses(
|
||||
ns, DefaultAccountNum, 1,
|
||||
internalAddr, err = scopedMgr.NextAddresses(
|
||||
ns, DefaultAccountNum, InternalBranch, 1,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to derive internal addr: %v", err)
|
||||
|
@ -2177,8 +2177,8 @@ func TestScopedKeyManagerManagement(t *testing.T) {
|
|||
err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error {
|
||||
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
|
||||
lastAddr, err = scopedMgr.LastExternalAddress(
|
||||
ns, DefaultAccountNum,
|
||||
lastAddr, err = scopedMgr.LastAddress(
|
||||
ns, DefaultAccountNum, ExternalBranch,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -2384,8 +2384,8 @@ func testNewRawAccount(t *testing.T, _ *Manager, db walletdb.DB,
|
|||
err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error {
|
||||
ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
|
||||
addrs, err := scopedMgr.NextExternalAddresses(
|
||||
ns, accountNum, 1,
|
||||
addrs, err := scopedMgr.NextAddresses(
|
||||
ns, accountNum, ExternalBranch, 1,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -404,8 +404,10 @@ func (s *ScopedKeyManager) loadAccountInfo(ns walletdb.ReadBucket,
|
|||
acctName: row.name,
|
||||
acctType: row.acctType,
|
||||
acctKeyEncrypted: row.privKeyEncrypted,
|
||||
nextExternalIndex: row.nextExternalIndex,
|
||||
nextInternalIndex: row.nextInternalIndex,
|
||||
nextIndex: [2]uint32{
|
||||
row.nextExternalIndex,
|
||||
row.nextInternalIndex,
|
||||
},
|
||||
}
|
||||
|
||||
// Use the crypto public key to decrypt the account public
|
||||
|
@ -437,49 +439,30 @@ func (s *ScopedKeyManager) loadAccountInfo(ns walletdb.ReadBucket,
|
|||
return nil, managerError(ErrDatabase, str, nil)
|
||||
}
|
||||
|
||||
// Derive and cache the managed address for the last external address.
|
||||
branch, index := ExternalBranch, acctInfo.nextExternalIndex
|
||||
if index > 0 {
|
||||
index--
|
||||
}
|
||||
lastExtAddrPath := DerivationPath{
|
||||
InternalAccount: account,
|
||||
Account: acctInfo.acctKeyPub.ChildIndex(),
|
||||
Branch: branch,
|
||||
Index: index,
|
||||
MasterKeyFingerprint: acctInfo.masterKeyFingerprint,
|
||||
}
|
||||
lastExtKey, err := s.deriveKey(acctInfo, branch, index, hasPrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lastExtAddr, err := s.keyToManaged(lastExtKey, lastExtAddrPath, acctInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
acctInfo.lastExternalAddr = lastExtAddr
|
||||
for branch := 0; branch < 2; branch++ {
|
||||
|
||||
// Derive and cache the managed address for the last internal address.
|
||||
branch, index = InternalBranch, acctInfo.nextInternalIndex
|
||||
// Derive and cache the managed address for the last external address.
|
||||
index := acctInfo.nextIndex[branch]
|
||||
if index > 0 {
|
||||
index--
|
||||
}
|
||||
lastIntAddrPath := DerivationPath{
|
||||
lastAddrPath := DerivationPath{
|
||||
InternalAccount: account,
|
||||
Account: acctInfo.acctKeyPub.ChildIndex(),
|
||||
Branch: branch,
|
||||
Branch: uint32(branch),
|
||||
Index: index,
|
||||
MasterKeyFingerprint: acctInfo.masterKeyFingerprint,
|
||||
}
|
||||
lastIntKey, err := s.deriveKey(acctInfo, branch, index, hasPrivateKey)
|
||||
lastKey, err := s.deriveKey(acctInfo, uint32(branch), index, hasPrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lastIntAddr, err := s.keyToManaged(lastIntKey, lastIntAddrPath, acctInfo)
|
||||
lastAddr, err := s.keyToManaged(lastKey, lastAddrPath, acctInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
acctInfo.lastInternalAddr = lastIntAddr
|
||||
acctInfo.lastAddr[branch] = lastAddr
|
||||
}
|
||||
|
||||
// Add it to the cache and return it when everything is successful.
|
||||
s.acctInfo[account] = acctInfo
|
||||
|
@ -516,8 +499,8 @@ func (s *ScopedKeyManager) AccountProperties(ns walletdb.ReadBucket,
|
|||
return nil, err
|
||||
}
|
||||
props.AccountName = acctInfo.acctName
|
||||
props.ExternalKeyCount = acctInfo.nextExternalIndex
|
||||
props.InternalKeyCount = acctInfo.nextInternalIndex
|
||||
props.ExternalKeyCount = acctInfo.nextIndex[ExternalBranch]
|
||||
props.InternalKeyCount = acctInfo.nextIndex[InternalBranch]
|
||||
props.AccountPubKey = acctInfo.acctKeyPub
|
||||
props.MasterKeyFingerprint = acctInfo.masterKeyFingerprint
|
||||
props.AddrSchema = acctInfo.addrSchema
|
||||
|
@ -938,7 +921,7 @@ func (s *ScopedKeyManager) accountAddrType(acctInfo *accountInfo,
|
|||
//
|
||||
// This function MUST be called with the manager lock held for writes.
|
||||
func (s *ScopedKeyManager) nextAddresses(ns walletdb.ReadWriteBucket,
|
||||
account uint32, numAddresses uint32, internal bool) ([]ManagedAddress, error) {
|
||||
account uint32, branch uint32, numAddresses uint32) ([]ManagedAddress, error) {
|
||||
|
||||
// The next address can only be generated for accounts that have
|
||||
// already been created.
|
||||
|
@ -956,16 +939,12 @@ func (s *ScopedKeyManager) nextAddresses(ns walletdb.ReadWriteBucket,
|
|||
|
||||
// Choose the branch key and index depending on whether or not this is
|
||||
// an internal address.
|
||||
branchNum, nextIndex := ExternalBranch, acctInfo.nextExternalIndex
|
||||
if internal {
|
||||
branchNum = InternalBranch
|
||||
nextIndex = acctInfo.nextInternalIndex
|
||||
}
|
||||
nextIndex := acctInfo.nextIndex[branch]
|
||||
|
||||
// Choose the appropriate type of address to derive since it's possible
|
||||
// for a watch-only account to have a different schema from the
|
||||
// manager's.
|
||||
addrType := s.accountAddrType(acctInfo, internal)
|
||||
addrType := s.accountAddrType(acctInfo, branch == InternalBranch)
|
||||
|
||||
// Ensure the requested number of addresses doesn't exceed the maximum
|
||||
// allowed for this account.
|
||||
|
@ -978,10 +957,9 @@ func (s *ScopedKeyManager) nextAddresses(ns walletdb.ReadWriteBucket,
|
|||
}
|
||||
|
||||
// Derive the appropriate branch key and ensure it is zeroed when done.
|
||||
branchKey, err := acctKey.Derive(branchNum)
|
||||
branchKey, err := acctKey.Derive(branch)
|
||||
if err != nil {
|
||||
str := fmt.Sprintf("failed to derive extended key branch %d",
|
||||
branchNum)
|
||||
str := fmt.Sprintf("failed to derive extended key branch %d", branch)
|
||||
return nil, managerError(ErrKeyChain, str, err)
|
||||
}
|
||||
defer branchKey.Zero() // Ensure branch key is zeroed when done.
|
||||
|
@ -1021,7 +999,7 @@ func (s *ScopedKeyManager) nextAddresses(ns walletdb.ReadWriteBucket,
|
|||
derivationPath := DerivationPath{
|
||||
InternalAccount: account,
|
||||
Account: acctKey.ChildIndex(),
|
||||
Branch: branchNum,
|
||||
Branch: branch,
|
||||
Index: nextIndex - 1,
|
||||
}
|
||||
|
||||
|
@ -1035,15 +1013,13 @@ func (s *ScopedKeyManager) nextAddresses(ns walletdb.ReadWriteBucket,
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if internal {
|
||||
addr.internal = true
|
||||
}
|
||||
addr.internal = branch == InternalBranch
|
||||
managedAddr := addr
|
||||
nextKey.Zero()
|
||||
|
||||
info := unlockDeriveInfo{
|
||||
managedAddr: managedAddr,
|
||||
branch: branchNum,
|
||||
branch: branch,
|
||||
index: nextIndex - 1,
|
||||
}
|
||||
addressInfo = append(addressInfo, &info)
|
||||
|
@ -1113,13 +1089,8 @@ func (s *ScopedKeyManager) nextAddresses(ns walletdb.ReadWriteBucket,
|
|||
|
||||
// Set the last address and next address for tracking.
|
||||
ma := addressInfo[len(addressInfo)-1].managedAddr
|
||||
if internal {
|
||||
acctInfo.nextInternalIndex = nextIndex
|
||||
acctInfo.lastInternalAddr = ma
|
||||
} else {
|
||||
acctInfo.nextExternalIndex = nextIndex
|
||||
acctInfo.lastExternalAddr = ma
|
||||
}
|
||||
acctInfo.nextIndex[branch] = nextIndex
|
||||
acctInfo.lastAddr[branch] = ma
|
||||
}
|
||||
ns.Tx().OnCommit(onCommit)
|
||||
|
||||
|
@ -1152,16 +1123,12 @@ func (s *ScopedKeyManager) extendAddresses(ns walletdb.ReadWriteBucket,
|
|||
|
||||
// Choose the branch key and index depending on whether or not this is
|
||||
// an internal address.
|
||||
branchNum, nextIndex := ExternalBranch, acctInfo.nextExternalIndex
|
||||
if internal {
|
||||
branchNum = InternalBranch
|
||||
nextIndex = acctInfo.nextInternalIndex
|
||||
}
|
||||
nextIndex := acctInfo.nextIndex[branch]
|
||||
|
||||
// Choose the appropriate type of address to derive since it's possible
|
||||
// for a watch-only account to have a different schema from the
|
||||
// manager's.
|
||||
addrType := s.accountAddrType(acctInfo, internal)
|
||||
addrType := s.accountAddrType(acctInfo, branch == InternalBranch)
|
||||
|
||||
// If the last index requested is already lower than the next index, we
|
||||
// can return early.
|
||||
|
@ -1179,10 +1146,10 @@ func (s *ScopedKeyManager) extendAddresses(ns walletdb.ReadWriteBucket,
|
|||
}
|
||||
|
||||
// Derive the appropriate branch key and ensure it is zeroed when done.
|
||||
branchKey, err := acctKey.Derive(branchNum)
|
||||
branchKey, err := acctKey.Derive(branch)
|
||||
if err != nil {
|
||||
str := fmt.Sprintf("failed to derive extended key branch %d",
|
||||
branchNum)
|
||||
branch)
|
||||
return managerError(ErrKeyChain, str, err)
|
||||
}
|
||||
defer branchKey.Zero() // Ensure branch key is zeroed when done.
|
||||
|
@ -1224,7 +1191,7 @@ func (s *ScopedKeyManager) extendAddresses(ns walletdb.ReadWriteBucket,
|
|||
derivationPath := DerivationPath{
|
||||
InternalAccount: account,
|
||||
Account: acctInfo.acctKeyPub.ChildIndex(),
|
||||
Branch: branchNum,
|
||||
Branch: branch,
|
||||
Index: nextIndex - 1,
|
||||
}
|
||||
|
||||
|
@ -1238,15 +1205,13 @@ func (s *ScopedKeyManager) extendAddresses(ns walletdb.ReadWriteBucket,
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if internal {
|
||||
addr.internal = true
|
||||
}
|
||||
addr.internal = branch == InternalBranch
|
||||
managedAddr := addr
|
||||
nextKey.Zero()
|
||||
|
||||
info := unlockDeriveInfo{
|
||||
managedAddr: managedAddr,
|
||||
branch: branchNum,
|
||||
branch: branch,
|
||||
index: nextIndex - 1,
|
||||
}
|
||||
addressInfo = append(addressInfo, &info)
|
||||
|
@ -1302,21 +1267,16 @@ func (s *ScopedKeyManager) extendAddresses(ns walletdb.ReadWriteBucket,
|
|||
|
||||
// Set the last address and next address for tracking.
|
||||
ma := addressInfo[len(addressInfo)-1].managedAddr
|
||||
if internal {
|
||||
acctInfo.nextInternalIndex = nextIndex
|
||||
acctInfo.lastInternalAddr = ma
|
||||
} else {
|
||||
acctInfo.nextExternalIndex = nextIndex
|
||||
acctInfo.lastExternalAddr = ma
|
||||
}
|
||||
acctInfo.nextIndex[branch] = nextIndex
|
||||
acctInfo.lastAddr[branch] = ma
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NextExternalAddresses returns the specified number of next chained addresses
|
||||
// NextAddresses returns the specified number of next chained addresses
|
||||
// that are intended for external use from the address manager.
|
||||
func (s *ScopedKeyManager) NextExternalAddresses(ns walletdb.ReadWriteBucket,
|
||||
account uint32, numAddresses uint32) ([]ManagedAddress, error) {
|
||||
func (s *ScopedKeyManager) NextAddresses(ns walletdb.ReadWriteBucket,
|
||||
account uint32, branch uint32, numAddresses uint32) ([]ManagedAddress, error) {
|
||||
|
||||
// Enforce maximum account number.
|
||||
if account > MaxAccountNum {
|
||||
|
@ -1327,32 +1287,15 @@ func (s *ScopedKeyManager) NextExternalAddresses(ns walletdb.ReadWriteBucket,
|
|||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
|
||||
return s.nextAddresses(ns, account, numAddresses, false)
|
||||
}
|
||||
|
||||
// NextInternalAddresses returns the specified number of next chained addresses
|
||||
// that are intended for internal use such as change from the address manager.
|
||||
func (s *ScopedKeyManager) NextInternalAddresses(ns walletdb.ReadWriteBucket,
|
||||
account uint32, numAddresses uint32) ([]ManagedAddress, error) {
|
||||
|
||||
// Enforce maximum account number.
|
||||
if account > MaxAccountNum {
|
||||
err := managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
|
||||
return s.nextAddresses(ns, account, numAddresses, true)
|
||||
return s.nextAddresses(ns, account, branch, numAddresses)
|
||||
}
|
||||
|
||||
// ExtendExternalAddresses ensures that all valid external keys through
|
||||
// lastIndex are derived and stored in the wallet. This is used to ensure that
|
||||
// wallet's persistent state catches up to a external child that was found
|
||||
// during recovery.
|
||||
func (s *ScopedKeyManager) ExtendExternalAddresses(ns walletdb.ReadWriteBucket,
|
||||
account uint32, lastIndex uint32) error {
|
||||
func (s *ScopedKeyManager) ExtendAddresses(ns walletdb.ReadWriteBucket,
|
||||
account uint32, branch uint32, lastIndex uint32) error {
|
||||
|
||||
if account > MaxAccountNum {
|
||||
err := managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil)
|
||||
|
@ -1362,28 +1305,10 @@ func (s *ScopedKeyManager) ExtendExternalAddresses(ns walletdb.ReadWriteBucket,
|
|||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
|
||||
return s.extendAddresses(ns, account, lastIndex, false)
|
||||
return s.extendAddresses(ns, account, branch, lastIndex)
|
||||
}
|
||||
|
||||
// ExtendInternalAddresses ensures that all valid internal keys through
|
||||
// lastIndex are derived and stored in the wallet. This is used to ensure that
|
||||
// wallet's persistent state catches up to an internal child that was found
|
||||
// during recovery.
|
||||
func (s *ScopedKeyManager) ExtendInternalAddresses(ns walletdb.ReadWriteBucket,
|
||||
account uint32, lastIndex uint32) error {
|
||||
|
||||
if account > MaxAccountNum {
|
||||
err := managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
|
||||
return s.extendAddresses(ns, account, lastIndex, true)
|
||||
}
|
||||
|
||||
// LastExternalAddress returns the most recently requested chained external
|
||||
// LastAddress returns the most recently requested chained external
|
||||
// address from calling NextExternalAddress for the given account. The first
|
||||
// external address for the account will be returned if none have been
|
||||
// previously requested.
|
||||
|
@ -1391,8 +1316,8 @@ func (s *ScopedKeyManager) ExtendInternalAddresses(ns walletdb.ReadWriteBucket,
|
|||
// This function will return an error if the provided account number is greater
|
||||
// than the MaxAccountNum constant or there is no account information for the
|
||||
// passed account. Any other errors returned are generally unexpected.
|
||||
func (s *ScopedKeyManager) LastExternalAddress(ns walletdb.ReadBucket,
|
||||
account uint32) (ManagedAddress, error) {
|
||||
func (s *ScopedKeyManager) LastAddress(ns walletdb.ReadBucket,
|
||||
account, branch uint32) (ManagedAddress, error) {
|
||||
|
||||
// Enforce maximum account number.
|
||||
if account > MaxAccountNum {
|
||||
|
@ -1410,47 +1335,13 @@ func (s *ScopedKeyManager) LastExternalAddress(ns walletdb.ReadBucket,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if acctInfo.nextExternalIndex > 0 {
|
||||
return acctInfo.lastExternalAddr, nil
|
||||
if acctInfo.nextIndex[branch] > 0 {
|
||||
return acctInfo.lastAddr[branch], nil
|
||||
}
|
||||
|
||||
return nil, managerError(ErrAddressNotFound, "no previous external address", nil)
|
||||
}
|
||||
|
||||
// LastInternalAddress returns the most recently requested chained internal
|
||||
// address from calling NextInternalAddress for the given account. The first
|
||||
// internal address for the account will be returned if none have been
|
||||
// previously requested.
|
||||
//
|
||||
// This function will return an error if the provided account number is greater
|
||||
// than the MaxAccountNum constant or there is no account information for the
|
||||
// passed account. Any other errors returned are generally unexpected.
|
||||
func (s *ScopedKeyManager) LastInternalAddress(ns walletdb.ReadBucket,
|
||||
account uint32) (ManagedAddress, error) {
|
||||
|
||||
// Enforce maximum account number.
|
||||
if account > MaxAccountNum {
|
||||
err := managerError(ErrAccountNumTooHigh, errAcctTooHigh, nil)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.mtx.Lock()
|
||||
defer s.mtx.Unlock()
|
||||
|
||||
// Load account information for the passed account. It is typically
|
||||
// cached, but if not it will be loaded from the database.
|
||||
acctInfo, err := s.loadAccountInfo(ns, account)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if acctInfo.nextInternalIndex > 0 {
|
||||
return acctInfo.lastInternalAddr, nil
|
||||
}
|
||||
|
||||
return nil, managerError(ErrAddressNotFound, "no previous internal address", nil)
|
||||
}
|
||||
|
||||
// NewRawAccount creates a new account for the scoped manager. This method
|
||||
// differs from the NewAccount method in that this method takes the account
|
||||
// number *directly*, rather than taking a string name for the account, then
|
||||
|
|
|
@ -326,14 +326,14 @@ func (w *Wallet) ImportAccountDryRun(name string,
|
|||
// attempt, we'll want to invalidate the cache for it.
|
||||
defer manager.InvalidateAccountCache(accountProps.AccountNumber)
|
||||
|
||||
externalAddrs, err = manager.NextExternalAddresses(
|
||||
ns, accountProps.AccountNumber, numAddrs,
|
||||
externalAddrs, err = manager.NextAddresses(
|
||||
ns, accountProps.AccountNumber, waddrmgr.ExternalBranch, numAddrs,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
internalAddrs, err = manager.NextInternalAddresses(
|
||||
ns, accountProps.AccountNumber, numAddrs,
|
||||
internalAddrs, err = manager.NextAddresses(
|
||||
ns, accountProps.AccountNumber, waddrmgr.InternalBranch, numAddrs,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -261,11 +261,7 @@ func (rs *RecoveryState) AddWatchedOutPoint(outPoint *wire.OutPoint,
|
|||
type ScopeRecoveryState struct {
|
||||
// ExternalBranch is the recovery state of addresses generated for
|
||||
// external use, i.e. receiving addresses.
|
||||
ExternalBranch *BranchRecoveryState
|
||||
|
||||
// InternalBranch is the recovery state of addresses generated for
|
||||
// internal use, i.e. change addresses.
|
||||
InternalBranch *BranchRecoveryState
|
||||
AccountBranches [][2]*BranchRecoveryState
|
||||
}
|
||||
|
||||
// NewScopeRecoveryState initializes an ScopeRecoveryState with the chosen
|
||||
|
|
|
@ -954,22 +954,12 @@ func expandScopeHorizons(ns walletdb.ReadWriteBucket,
|
|||
return nil
|
||||
}
|
||||
|
||||
// externalKeyPath returns the relative external derivation path /0/0/index.
|
||||
func externalKeyPath(index uint32) waddrmgr.DerivationPath {
|
||||
// keyPath returns the relative external derivation path /account/branch/index.
|
||||
func keyPath(account, branch, index uint32) waddrmgr.DerivationPath {
|
||||
return waddrmgr.DerivationPath{
|
||||
InternalAccount: waddrmgr.DefaultAccountNum,
|
||||
Account: waddrmgr.DefaultAccountNum,
|
||||
Branch: waddrmgr.ExternalBranch,
|
||||
Index: index,
|
||||
}
|
||||
}
|
||||
|
||||
// internalKeyPath returns the relative internal derivation path /0/1/index.
|
||||
func internalKeyPath(index uint32) waddrmgr.DerivationPath {
|
||||
return waddrmgr.DerivationPath{
|
||||
InternalAccount: waddrmgr.DefaultAccountNum,
|
||||
Account: waddrmgr.DefaultAccountNum,
|
||||
Branch: waddrmgr.InternalBranch,
|
||||
InternalAccount: account,
|
||||
Account: account,
|
||||
Branch: branch,
|
||||
Index: index,
|
||||
}
|
||||
}
|
||||
|
@ -982,8 +972,7 @@ func newFilterBlocksRequest(batch []wtxmgr.BlockMeta,
|
|||
|
||||
filterReq := &chain.FilterBlocksRequest{
|
||||
Blocks: batch,
|
||||
ExternalAddrs: make(map[waddrmgr.ScopedIndex]btcutil.Address),
|
||||
InternalAddrs: make(map[waddrmgr.ScopedIndex]btcutil.Address),
|
||||
Addresses: make(map[waddrmgr.ScopedIndex]btcutil.Address),
|
||||
WatchedOutPoints: recoveryState.WatchedOutPoints(),
|
||||
}
|
||||
|
||||
|
@ -1112,23 +1101,12 @@ func logFilterBlocksResp(block wtxmgr.BlockMeta,
|
|||
resp *chain.FilterBlocksResponse) {
|
||||
|
||||
// Log the number of external addresses found in this block.
|
||||
var nFoundExternal int
|
||||
for _, indexes := range resp.FoundExternalAddrs {
|
||||
nFoundExternal += len(indexes)
|
||||
}
|
||||
if nFoundExternal > 0 {
|
||||
log.Infof("Recovered %d external addrs at height=%d hash=%v",
|
||||
nFoundExternal, block.Height, block.Hash)
|
||||
}
|
||||
var nFoundAddresses int
|
||||
nFoundAddresses += len(resp.FoundAddresses)
|
||||
|
||||
// Log the number of internal addresses found in this block.
|
||||
var nFoundInternal int
|
||||
for _, indexes := range resp.FoundInternalAddrs {
|
||||
nFoundInternal += len(indexes)
|
||||
}
|
||||
if nFoundInternal > 0 {
|
||||
log.Infof("Recovered %d internal addrs at height=%d hash=%v",
|
||||
nFoundInternal, block.Height, block.Hash)
|
||||
if nFoundAddresses > 0 {
|
||||
log.Infof("Recovered %d addrs at height=%d hash=%v",
|
||||
nFoundAddresses, block.Height, block.Hash)
|
||||
}
|
||||
|
||||
// Log the number of outpoints found in this block.
|
||||
|
@ -1568,7 +1546,7 @@ func (w *Wallet) CurrentAddress(account uint32, scope waddrmgr.KeyScope) (btcuti
|
|||
)
|
||||
err = walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
|
||||
addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
maddr, err := manager.LastExternalAddress(addrmgrNs, account)
|
||||
maddr, err := manager.LastAddress(addrmgrNs, account, waddrmgr.ExternalBranch)
|
||||
if err != nil {
|
||||
// If no address exists yet, create the first external
|
||||
// address.
|
||||
|
@ -2954,7 +2932,7 @@ func (w *Wallet) newAddress(addrmgrNs walletdb.ReadWriteBucket, account uint32,
|
|||
}
|
||||
|
||||
// Get next address from wallet.
|
||||
addrs, err := manager.NextExternalAddresses(addrmgrNs, account, 1)
|
||||
addrs, err := manager.NextAddresses(addrmgrNs, account, waddrmgr.ExternalBranch, 1)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -3012,7 +2990,7 @@ func (w *Wallet) newChangeAddress(addrmgrNs walletdb.ReadWriteBucket,
|
|||
}
|
||||
|
||||
// Get next chained change address from wallet for account.
|
||||
addrs, err := manager.NextInternalAddresses(addrmgrNs, account, 1)
|
||||
addrs, err := manager.NextAddresses(addrmgrNs, account, waddrmgr.InternalBranch, 1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue