-
Notifications
You must be signed in to change notification settings - Fork 578
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
wallet: support derived public key import #732
Conversation
cc @guggero |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did a first pass, looks pretty good!
Since I wasn't very familiar with the code base it took me a while to grok all the changes. It is easy to underestimate the complexity here. So great work on this, the diff reads well once one understands the context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really close now! Added a suggestions w.r.t how to handle bip49plus vs the regular bip 49. I think that's the only proper blocking comment I have in this diff.
I think this is only missing the change to "undo" the creation of the BIP 49+ key scope. If we don't want to break some other callers (like lnd perhaps), then we can just change the mapping in |
@Roasbeef @guggero PTAL! A few things have changed in the latest diff:
@Roasbeef could you clear the Travis build cache? I'm not sure why |
@wpaulino oddly, the repo doesn't actually have any build caches... |
I ran it locally and eventually got this after running it twice:
I don't think this has been popping up for any other PRs though? |
The first time it ran it actually modified a set of checked in protos, then after running it again it finally sent out a proper error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🏊♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to use a default version when serializing instead of returning an error. This currently causes the lnd itests to fail.
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.
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.
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.
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.
Co-authored-by: Oliver Gugger <[email protected]>
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Travis is failing, otherwise LGTM 💯
The linter doesn't produce any failures locally, and it doesn't seem to return what's wrong on Travis. Waiting for @Roasbeef to report back. |
I can confirm that Merging so we can see if the issue perists once it's running against master. |
In this PR, we build upon #667 to introduce support for importing master/derived public keys into the wallet. This has been a much requested feature by
lnd
users that will allow them to minimize their hot wallet risks. Master public keys, commonly referred to asxpub
s, must have a derivation path of the formm/purpose'/coin_type'/account'
, while derived public keys must have a derivation path of the formm/purpose'/coin_type'/account'/branch/index
. As of now, care must be taken to ensure any watch-only accounts/derived public keys imported have not been used, as the functionality to rescan for their previous activity is not supported yet.