Skip to content
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

Feature to share address privkeys with VSPs #1613

Open
itswisdomagain opened this issue Nov 13, 2019 · 3 comments
Open

Feature to share address privkeys with VSPs #1613

itswisdomagain opened this issue Nov 13, 2019 · 3 comments

Comments

@itswisdomagain
Copy link
Member

This issue is the result of collaborative research between myself and @raedah, taking into account suggestions and inputs from various other devs in chat.

Current approach to sharing ticket voting rights with VSPs

In order for VSPs to vote on user-purchased tickets, they need to have voting rights to the ticket address.
Currently, VSPs generate 1-of-2 multisigs using pubkey addresses derived from the user's wallet and the VSPs' voting wallet.

Problem - Privacy onchain with tickets purchased using VSPs

A significant problem with the current VSP system is voting address reuse per user, making ticket correlation possible which impacts privacy. The solution proposed below recommends solving this problem by providing a means for users to export and share different voting address privkeys with VSPs. VSPs will however need to first migrate away from a user account-based system in order to support multiple voting addresses per user. decred/dcrstakepool#568 presents details of this transition.

Another problem with the current approach is described by @matheusd in #1217:

"One downside of the current voting pool integration is that you're required to backup the redeem script for your tickets of a given pool before at least one vote or revoke has been published for them, since it's possible (even though unlikely) that both the pool and your wallet are lost before that happens and you need to send a vote or revocation tx (which requires having access to the script).

This adds another bit of information that a conscientious user needs to back up besides their seed, and this is not very prominently advertised in our documentation and UI."

Proposed Solution

It was proposed in the issue referenced above "to use a separate branch of the bip32 wallet (possibly starting at a different purpose branch) to provide the source of data to share to the voting pool".

This would make it possible for users to regain voting rights to VSP tickets while restoring their wallet from seed, without depending on a VSP to retrieve redeem scripts and without having to maintain a separate record of VSP-generated redeem scripts.

It was initially proposed to allow users share extended private keys with VSPs. Instead of one multisig address per user, VSPs would store the user-shared xpriv per user account; and use this xpriv to derive different voting addresses for the same user as a step towards reducing ticket correlation but this only partly improves anonymity as VSPs will continue to be able to link multiple tickets to a user.

It was later decided to export and share single address private keys per ticket with VSPs instead of an xpriv.

The proposed solution (as revised) is to derive ticket/voting addresses off the user's HD wallet and the private key for each ticket address shared with a VSP. With the ticket/voting address coming solely from the user's HD wallet, the private key for ticket addresses can be re-derived during wallet restoration from seed without needing to communicate with any VSP.

Discussions around this proposed solution has birthed the following 3 possible approaches:

Proposed Approach 1 - Derive ticket/voting addresses from a new BIP43 purpose field of the user's HD wallet

The derivation path for addresses derived using this approach will be m / <purpose_field>' / <address_index>'.
It has been suggested to use "vsp" unicode value (14679) as <purpose_field> number.
Hardened derivation is to be used on both purpose field and address levels of this HD path.

Pros

  • Having access to an address privkey and the parent xpub does not give an attacker the ability to derive other address privkeys because of using hardened derivation.
  • As mentioned by @davecgh, using a different purpose field makes semantic sense since addresses derived off this purpose field serve a special purpose - voting.
  • Unlike with regular accounts (regardless of the branch used), no provision will be made to export xpubs from this purpose node, to prevent onchain tickets correlation.
  • Quite easy to support multiple voting accounts using the HD path m / <purpose_field>' / <account>' / <address_index>'.

Cons

  • Requires users to re-seed, which as pointed out by @matheusd sets a bad precedent for dcrwallet requesting users to enter their seed after setting up their wallet; which precedent could be exploited by malicious actors to defraud users.
  • Potentially more work required to implement, also considering that decrediton would also need to implement a reseeding feature that would most likely only be used once.

Proposed Approach 2 - Derive ticket/voting addresses from a custom BIP44 branch index of the user's BIP32 wallet

The derivation path for addresses derived using this approach will be m / 44' / <coin_type>' / <account>' / <custom_branch>' / <address_index>'.
A custom branch index (other than 0 and 1 which are reserved as defined in the BIP44 spec) will need to be selected.
Also, hardened derivation will be used at the branch and address levels to eliminate the possibility of an attacker being able to derive the extended privkey for this account given access to the account's xpub and any child address privkey.

Additionally (perhaps optionally), as noted by @davecgh, dcrwallet should also "not allow exporting the extended public key associated with the hardened branch as a matter of safety because, while using hardened address indexes will prevent a mailicious actor from reconstructing the associated extended private key should they happen to get ahold of the private key shared with a VSP and the extended public key of the hardened branch, the extended public key alone will still leak all of the address used for the voting addresses and thus destory privacy, especially if you're mixing."

Aside from deciding on a constant custom branch index to use, there's also a need to decide the account index off of which the branch and addresses will be derived using this approach. 2 possibilities exist here:

  • The voting address of a ticket (with it's sharable privkey ofc) can be derived off the custom branch of the same account used for purchasing the ticket. This has the advantage of providing inherent support for multiple voting accounts; as simple as using different accounts for ticket purchase.
  • Alternatively, a constant account index (say 0) is selected and used for all voting keys derivation. To support multiple voting accounts, the HD path will need to be modified to include another level, producing m /44' / <coin_type>' / <selected_constant_account_index>' / <custom_branch>' / <voting account>' / <address_index>'.

Pros

  • Potentially easier to implement.
  • Does not require re-seeding.
  • Having access to an address privkey and the parent account xpub does not give an attacker the ability to derive other address privkeys IF hardened derivation is used at the branch and address levels.

Cons

  • Supporting multiple voting accounts on a fixed account index would require a deviation from the BIP44 spec given the suggestion to use m /44' / <coin_type>' / 0' / <custom_branch>' / <voting account>' / <address_index>' (6 levels instead of the 5 levels defined in the BIP44 spec).
  • If hardened derivation is NOT used at the branch and address levels, anyone with access to this account's extended pubkey and any child address privkey will be able to derive private keys for other addresses of this account - including external and internal addresses meant to handle funds; and dcrwallet contains a function to export account xpubs.
  • If xpub export is not disabled for the account associated with the custom branch, the general ease of exporting account xpubs becomes a real privacy risk. Especially since, as noted by @davecgh, public extended keys are, as their very name suggests, something that is generally safe to share publicly.

Proposed Approach 3 - Derive ticket/voting addresses from a regular BIP44 account of the user's BIP32 wallet

The derivation path for addresses derived using this approach will be m / 44' / <coin_type>' / <reserved_account>' / 0 / <address_index>.
An account number will need to be dedicated for this purpose as is done for the imported account.
An alternative that has been mentioned is to allow users decide which account to set aside for this purpose; and during wallet restore from seed, we rely on the nature of tx ntfns gotten to infer the voting account.

Pros

  • Potentially easiest to implement.
  • Does not require re-seeding.
  • Does not deviate from the BIP44 spec.
  • Access to this account's xpub and any child address privkey will compromise other address privkeys in this account but this would be considerably safe as long as this account does not hold funds.

Cons

  • Users could easily mistakenly use addresses derived from this reserved account to receive funds.
  • Would require cutting off a portion of the BIP44 address space from general use.
  • Anyone with access to this account's extended pubkey and any child address privkey will be able to derive private keys for other addresses of this account; and dcrwallet contains a function to export account xpubs. This would give such one the ability to vote on tickets with voting addresses derived from this account.
  • Because of the very present and quite easy-to-use dcrwallet feature to export xpubs for regular accounts, exposing this account's xpub presents a serious privacy concern.

Recommended Approach - Approach 2

Approach 2 - Derive ticket/voting addresses from a custom BIP44 branch index stands out as requiring the least amount of work to implement while providing security against malicious re-calculation of account extended keys from xpubs and any child address privkey.
For this recommended implementation, each ticket's voting address and shareable privkey would be derived off the custom branch index of the same account used to purchase the ticket.

@xaur
Copy link

xaur commented Dec 3, 2019

Great work compiling this together.

I like sharing individual ticket voting privkeys with the VSP more than other solutions seen so far:

  • it simplifies the shared state that must be exchanged and stored by the VSP to "1 ticket - 1 voting privkey - voting prefs"
  • allows to eliminate VSP accounts
    • without accounts VSPs can correlate even less information than they could if voting address reuse was eliminated but the accounts remained
  • eliminates the redeem script hassle (huge UX win)
  • does not introduce shared xpriv hassle
    • which require accounts

(please correct if I got it wrong)

Can't tell which approach is better, but I'd like to have all privkeys that are shared with a 3rd party to be somehow isolated from the rest of wallet keys.

From perspective of the user that doesn't mind reseeding, what are the advantages of Approach 1 over Approach 2?

@jrick
Copy link
Member

jrick commented Dec 9, 2019

I'm generally leaning towards some solution with a new purpose key (requires reseed, but only if you require these keys).

From perspective of the user that doesn't mind reseeding, what are the advantages of Approach 1 over Approach 2?

For implementers, it makes the code a little clearer (and possibly reusable, if other wallets are ported, they can continue using their existing BIP0044 designs with minimal changes) since we would not be modifying or extending BIP0044 with what it does not specify. We also need to take into consideration that further designs or versions of BIP0044 may build on the current BIP0044 by using extra branches, and we would be unable to satisify these requirements if we impede on these branches.

By separating the current account handling from these keys, we also can prevent a lot of misuse of these keys just by the design, e.g. by not allowing xpubs to be exported.

Key handling in the wallet db is already abstract enough that we don't really need to worry about where the keys are derived from just to save them, as they can be derived on the fly using just their path and a parent key.

Finally, extending BIP0044 may mean complicating the account and address discovery phases especially if we use new branches under existing BIP0044 accounts. This would increase the cost to discover used accounts by 50%, and would similarly increase the cost to rediscover each branch's last used address as there would be more branches to check.

The only downside I see is the requirement to reseed or reenter the seed, but this input can be deferred until it is actually needed to use this feature. Non-stakers and solo stakers would not need to use these keys.

@xaur
Copy link

xaur commented Dec 17, 2019

I always prefer "do it cleaner now" over "keep suffering later". Decred is 3 years old, but on the other hand, it is still not big/popular enough to make such changes too breaking.

If we go with the reseed/seed re-entry, we will upset the users with the migration pain but we can plan to minimize it:

  • VSP voters must be given enough time to go through this. As a random guess, I wouldn't be surprised if it takes 1 year for 50% of users to upgrade.
  • Reseed/seed re-entry migration could and should be coordinated and bundled with the transition from account-based to accountless ticket-based VSP. It's better to bother and do all the steps once, such as reseed and reconfigure the VSP voting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants