near / near-wallet-roadmap

near-wallet-roadmap
Apache License 2.0
8 stars 0 forks source link

Multiple HD Derivation path with Ledger Nano #6

Closed stefanopepe closed 3 years ago

stefanopepe commented 3 years ago

Summary As of today, wallet.near.org supports only a single derivation path, located at 44'/397'/0'/0'/1'. Therefore, NEAR webwallet supports only one account using Ledger Nano - even if the application on the Ledger device and near-cli are perfectly capable to generate and sign wallet pubkeys on any desired derivation path (44'/397'/0'/0'/n').

Intended Outcome As a power user, I want to leverage multiple pubkeys/derivation paths of my Ledger Nano wallet, such that I can manage more than one private key with the same physical device.

This new feature will help users who have more than one NEAR account, and will remove the need for near-cli on any pubkey that is different than 44'/397'/0'/0'/1'.

How will it work? While the backend and the API already support an arbitrary derivation path - such that one single Ledger Nano can manage multiple NEAR keys - the frontend is not yet able to manage them. This feature will integrate the low-level derivation path selection in the user interface, enabling power users to manage multiple keys from the same device.

heycorwin commented 3 years ago

@jimmy3dita @vgrichina In designing a way for the user to indicate specific HD paths, I'd like some more context on the optimal way that this might be done. For example, I understand this could be done in the following ways:

  1. Ask the user to define a range, so that the HD paths from within that range are added
  2. Ask the user to input a single or set of specific paths, not confined to a range
  3. Detect HD paths in use (not sure if this or something similar is possible?), display them to the user, and allow them to select which ones they would like to import.

Is this list comprehensive? Are there additional methods that should be considered?

kcole16 commented 3 years ago

This looks pretty comprehensive to me. #3 seems ideal to me, but requires some work to the Ledger app which may take some time. #1 is being used in the multistaker app reasonably well.

heycorwin commented 3 years ago

I agree #3 feels like the ideal. If that's not feasible short term though then I guess we'll need some kind of user input. Although I'd imagine we'd want to allow for input of more than just a range, incase users are leveraging HD paths that aren't subsequent. Something like:

  1. Show default HD path
  2. Import default or Add another HD Path (+)
  3. Enter path
  4. Import all

Users could add as many as they wanted. This is actually more straightforward then a range, and would also give advanced users more control (I would consider this an advanced feature anyway)

stefanopepe commented 3 years ago

I need some clarification on the high-level logic governing the keys.

From my understanding, we have two main scenarios:

  1. the creation of a new wallet
  2. the recovery/login of an existing wallet

// 1. creating a new wallet on the same Ledger This scenario requires to know which is the "first available free path", with a small margin for error: the same public key (so the same Ledger path) can be authorized on multiple accounts (@vgrichina correct me here), so we should know if the user is trying to create an account using a public key that was previously associated with another account.

This behavior is very common on near-cli: the same client can do "login" multiple times on multiple accounts. As a result, the very same public key can be used with multiple NEAR accounts.

So, let's say that I have an account alpha on the key path 44'/397'/0'/0'/1' and I want to generate a new account using the same Ledger. How should it work? We can:

  1. adopt the near-cli logic, such that the same public key (with the same path) can be used to control more than one account.
  2. adopt the near wallet logic, where every wallet is using its own seed, thus a different keypair.

There are important privacy implications (attaching the same public key to multiple accounts), so I would exclude 1 by now, and opt for 2. In the case of 2, we probably have to inform the user that we need to "spy" his Ledger, have him cycle through all the existing public keys (and accounts!) until we find the first empty one, and then inform him that the account beta was created using the key path 44'/397'/0'/0'/11'. Alternatively, we may ask the user to manually set the address, check if the pubkey is already in use, and eventually create an account.

// 2. wallet recovery/login This scenario is much easier to plan: we have a set of keys on the Ledger, and we ask the user to "press the [+] or [-] button" to cycle the variable x in the key path 44'/397'/0'/0'/x', to recover/login on the desired key. Every time a path is selected, and the user wants to recover it, they will have to press "recover", authorize the pubkey on the Ledger, and fetch the transactions on that wallet.

In this case, I suppose the user will be able to recover/login into more Ledger accounts, selecting the desired one from the top-right dropdown menu (as it is today).

Overall, I think that power users will be quite confident to select the right Ledger path and import the account. On the other hand, I'm worried that users that have no idea what is a path would have to add "accounts" (see this Ledger Live tutorial, and we might have to abstract the path into "multiple accounts" (see Trezor here)

TL;DR:

heycorwin commented 3 years ago

define if and how we may abstract the Ledger path selection and recovery, or "hide" the feature behind some advanced switch

@jimmy3dita yes I think it's safe to have things set to a "default" state where a single HD path is imported, and then allow the user to "expand" the sign-in experience to show the option to add or specify specific/multiple paths. First we should determine how we decide on the default path, though. Last used? Starting at 0? cc @vgrichina how is this choice made currently and does it make sense for it to change?

vgrichina commented 3 years ago

define if and how we may abstract the Ledger path selection and recovery, or "hide" the feature behind some advanced switch

@jimmy3dita yes I think it's safe to have things set to a "default" state where a single HD path is imported, and then allow the user to "expand" the sign-in experience to show the option to add or specify specific/multiple paths. First we should determine how we decide on the default path, though. Last used? Starting at 0? cc @vgrichina how is this choice made currently and does it make sense for it to change?

I think for v0 we should go with 0 by default and user editable path.

In ideal world we should keep last index on Ledger and have ability to scan multiple paths when importing from Ledger. But this requires updates to Ledger app which we ideally shouldn’t block on.

stefanopepe commented 3 years ago

@vgrichina I think we are all set with using the path 0 and starting from there. Do you also confirm we follow the behavior of one path=one wallet? How do we mitigate the risk that the same Ledger path is used for two different wallets? Some ideas:

  1. we check if that path is already used when the user confirms on the device, and we suggest picking the next one
  2. we simply don't care about the key, and we recover as many accounts as the ones associated with that Ledger path

Thanks =)

vgrichina commented 3 years ago

v0 is this IMO:

  1. we simply don't care about the key, and we recover as many accounts as the ones associated with that Ledger path

but this is good for v1:

  1. we check if that path is already used when the user confirms on the device, and we suggest picking the next one