mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-04 01:36:24 +01:00
keychain+lnwallet: when fetching priv keys or signing try to use cache
In this commit, we start to optimistically use the new private key cache that was added to btcwallet. As is, btcwallet will cache the decrypted account keys for each scope in memory. However, the existing methods to derive a child key from those account keys requires a write database transaction, and will re-derive the private key using BIP-32 each time. The newly added `DeriveFromKeyPathCache` lets us skip all this and directly use a cache assuming the account info is already cached. The new logic will try to use this method, but if it fails fall back to the existing `DeriveFromKeyPath` method. All calls after this will use this new cached key. Fixes https://github.com/lightningnetwork/lnd/issues/5125. Basic benchmark before the btcwallet change and after: ``` benchmark old ns/op new ns/op delta BenchmarkDerivePrivKey-8 22840583 125 -100.00% benchmark old allocs new allocs delta BenchmarkDerivePrivKey-8 89 2 -97.75% benchmark old bytes new bytes delta BenchmarkDerivePrivKey-8 10225 24 -99.77% ```
This commit is contained in:
parent
2206eba91a
commit
d6524ea517
2 changed files with 36 additions and 6 deletions
|
@ -252,14 +252,30 @@ func (b *BtcWalletKeyRing) DerivePrivKey(keyDesc KeyDescriptor) (
|
|||
|
||||
var key *btcec.PrivateKey
|
||||
|
||||
db := b.wallet.Database()
|
||||
err := walletdb.Update(db, func(tx walletdb.ReadWriteTx) error {
|
||||
addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
scope, err := b.keyScope()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scope, err := b.keyScope()
|
||||
if err != nil {
|
||||
return err
|
||||
// First, attempt to see if we can read the key directly from
|
||||
// btcwallet's internal cache, if we can then we can skip all the
|
||||
// operations below (fast path).
|
||||
if keyDesc.PubKey == nil {
|
||||
keyPath := waddrmgr.DerivationPath{
|
||||
InternalAccount: uint32(keyDesc.Family),
|
||||
Account: uint32(keyDesc.Family),
|
||||
Branch: 0,
|
||||
Index: keyDesc.Index,
|
||||
}
|
||||
privKey, err := scope.DeriveFromKeyPathCache(keyPath)
|
||||
if err == nil {
|
||||
return privKey, nil
|
||||
}
|
||||
}
|
||||
|
||||
db := b.wallet.Database()
|
||||
err = walletdb.Update(db, func(tx walletdb.ReadWriteTx) error {
|
||||
addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
|
||||
// If the account doesn't exist, then we may need to create it
|
||||
// for the first time in order to derive the keys that we
|
||||
|
|
|
@ -75,6 +75,20 @@ func (b *BtcWallet) deriveKeyByLocator(keyLoc keychain.KeyLocator) (*btcec.Priva
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// First try to read the key from the cached store, if this fails, then
|
||||
// we'll fall through to the method below that requires a database
|
||||
// transaction.
|
||||
path := waddrmgr.DerivationPath{
|
||||
InternalAccount: uint32(keyLoc.Family),
|
||||
Account: uint32(keyLoc.Family),
|
||||
Branch: 0,
|
||||
Index: keyLoc.Index,
|
||||
}
|
||||
privKey, err := scopedMgr.DeriveFromKeyPathCache(path)
|
||||
if err == nil {
|
||||
return privKey, nil
|
||||
}
|
||||
|
||||
var key *btcec.PrivateKey
|
||||
err = walletdb.Update(b.db, func(tx walletdb.ReadWriteTx) error {
|
||||
addrmgrNs := tx.ReadWriteBucket(waddrmgrNamespaceKey)
|
||||
|
|
Loading…
Add table
Reference in a new issue