With this commit we refactor the existing script address into a
baseScriptAddress struct and then add a new witnessScriptAddress type
that manages a pay-to-witness-script address.
Since CT can mean both Cipher Text as well as Clear Text, the variable
name scriptCT lead to confusion about its meaning. We rename it to make
it more clear how it's used.
Fixeslightningnetwork/lnd#5864.
The loadAccountInfo does load an account as its name suggests. But after
loading it, the account is also added to a map to cache it. That map
write should be seen as a writing operation and therefore the _write_
lock must be held, not just the read lock.
In this commit, we add a new method `DeriveFromKeyPathCache` that gives
callers a way to more quickly obtain a private key they know they'll be
using frequently. This method lets a caller avoid the write database
transaction as well as the EC operations to derive the key itself (BIP
32).
To allow a wallet to be created directly from an extended master root
key (xprv), we move the derivation from seed to extended key to the
loader instead of the address manager itself.
This method returns the first N external and internal addresses, which
can be presented to users to confirm whether the account has been
imported correctly.
Simnet was previously left out as it didn't have defined HD versions for
some of our key scopes. To allow testing importing accounts into simnet
wallets, we fall back to use the mainnet HD versions.
This commit also addresses an issue with simnet wallets that would arise
whenever ScopedKeyManager.AccountProperties was invoked:
`failed to retrieve account public key: unsupported net SimNet`
Following the previous commit, some external hardware signers require a
master key fingerprint to be present within the PSBT input derivation
paths so that the signer can recognize which inputs are relevant and
must be signed.
For key scopes which have an address schema where the external and
internal branches differ, we always assume that imported keys use the
external address type defined in the scope's address schema. This may
not always be the case however, and should be handled correctly.
Ideally, we generate two addresses per imported key (only if the
external and internal address types differ) and scan for both in the
chain.
This change was motivated by the need to support importing BIP-0049 keys
that use the standard address derivation scheme, where nested witness
pubkeys are used for both the external and internal branches. Our
BIP-0049 key scope is slightly different, in that addresses derived from
the internal branch use the witness pubkey address type. By having the
option of overriding the address schema for a particular account, we can
support importing standard BIP-0049 keys.
The master fingerprint corresponds to the fingerprint of the root master
public key (otherwise known as m/). This is required by some hardware
wallets for proper identification and signing.
The address schema is an optional field that allows an account to
override its corresponding address schema with a custom one.
Watch-only accounts are usually backed by an external signer as they do
not contain any private key information. Some external signers require a
root key fingerprint for identification and signing purposes. In order
to guarantee compatibility with external signers, we need to persist the
root key fingerprint within the database.
Before this change, watch-only accounts used the default account
database structure. In this commit, we introduce a new account type to
store different information for watch-only accounts only. This isn't a
breaking change as watch-only accounts have yet to be supported by the
primary user of the wallet (lnd). With this new account type, we can
avoid the empty private key fields, which are irrelevant to watch-only
accounts, and we can store the root key fingerprint.
Previously, addresses that belong to a watch-only account would have a
derivation path using the internal account number used to identify
accounts within the databse, rather than the actual account number based
on the account's master public key child index. This wasn't an issue
before as only one account would exist within the wallet, the 0 account,
which is also the default. To ensure users of the DerivationPath struct
can arrive at addresses correctly, we introduce a new field
InternalAccount to denote the internal account number and repurpose the
existing Account field to its actual meaning.
Not setting this would result in a non-sensible unix timestamp
(2288912640) being exposed when the wallet hasn't synced any blocks,
like in the case when it's waiting for the backend to sync.
This PR allows the creation of managers and accounts that are watch-only. The state of the database after creation would be identical to the state after calling
Manager.ConvertToWatchingOnly, assuming accounts with the right xpubs were created in the former case.
Co-authored-by: Ken Sedgwick <ken@bonsai.com>
Due to a no longer existing bug within the wallet, it was possible for
change addresses to be created outside of their intended key scope (the
default), so wallets affected by this now need to ensure they scan the
chain for all addresses within the default key scopes (as expected), and
all _internal_ addresses (branch used for change addresses) within any
other registered key scopes to reflect their proper balance.
The commit being reverted resulted in the discovery of a bug in which
change addresses could at times be created outside of the default key
scopes, causing us to not properly determine their spends.
It was discovered that the wallet can scan the chain for unnecessary
additional addresses that are derived by higher-level applications using
custom key scopes. This isn't much of an issue for full nodes, but it
can cause light clients to scan more than what's required, triggering
more false positive matches which lead to block retrieval.
Now, we'll only scan the chain for addresses that exist within the
default key scopes, as those are the only ones the wallet should be
concerned about.
We update the dropwtxmgr utility tool to take into account that the
wallet only stores MaxReorgDepth blocks, which introduced an additional
constraint when updating the wallet's synced state. The constraint
ensures that the previous block exists when updating the wallet's synced
state, but this does not hold for the birthday block since it's the
first block we'll store.
In this commit, we add a migration that will be used by existing wallets
to ensure they can adhere to the new requirement of storing up to
MaxReorgDepth entries within the block hash index.
In this commit, we modify the wallet's block hash index to only store up
to MaxReorgDepth blocks. This allows us to reduce consumed storage, as
we'd be mostly storing duplicate data. We choose to store up to
MaxReorgDepth to ensure we can recover from a potential long reorg.