monero-project / monero

Monero: the secure, private, untraceable cryptocurrency
https://getmonero.org
Other
8.78k stars 3.08k forks source link

[PROPOSAL] Encode restore height as 26th word of the mnemonic seed #6639

Open dEBRUYNE-1 opened 4 years ago

dEBRUYNE-1 commented 4 years ago

The restore height is currently a value that has to be entered manually for wallets that are restored from either the keys or the mnemonic seed. The wallet will essentially ignore blocks (only pulling block hashes) before the restore height and start scanning (looking for transactions that belong to the wallet) from the restore height block.

User experience is degraded if the user accidentally sets a restore height that is too 'high' (i.e. after the first transaction to the wallet), as the wallet will 'miss' certain or all transactions, thereby causing an improper balance (as well as transaction history) to be displayed.

In order to improve user experience, we could encode an approximate restore height as additional word of the mnemonic seed. The restore height would then be set automatically upon restoring the wallet, thereby ensuring users will not inadvertently set an erroneous restore height.

I personally do not see many drawbacks of this proposal. Guides will have to be updated to reflect the new format and users need to be informed. Users further, initially, may be slightly confused due to two different seed formats being present. However, I think ultimately the proposal is net beneficial to user experience.

tevador commented 4 years ago

then unflag this word by adding 0x539 mod 2048

Addition in GF is XOR, so you have to do 1282^1337 = 59.

knaccc commented 4 years ago

@tevador Thanks, our implementations are perfectly compatible now! https://github.com/knaccc/monero-seed-js

I just thought I'd double check my understanding of RS with you (w.r.t. this scenario with a one word checksum):

  1. If exactly one particular word is entered incorrectly, and all others are correct, and if the incorrect word is still a valid electrum word, then that error will always be detected. Although the error will be detected, it will not be possible to know which word in the mnemonic was incorrect.

  2. Therefore the seed can only be corrected if the incorrect word position is known, and if there is only one incorrect word. In this circumstance, brute forcing the word from the electrum list will always find exactly one word that causes the mnemonic to validate (as an implication of point 1), and a false positive is impossible when brute forcing the word known to be incorrect.

tevador commented 4 years ago

@knaccc

  1. Correct. Two different phrases phrases differing in just one word can never have the same checksum.

  2. Correct. I should add that I'm using bruteforcing for error correction because we have just one check word. There are (more complex) algorithms that can correct errors efficiently for an arbitrary number of check digits. See for example Berlekamp–Massey algorithm

knaccc commented 4 years ago

I cross-checked the electrum words list against an English dictionary, and there is one word that stood out: "satoshi".

I'd imagine that we should be taking that word out and adding in something else... suggestions?

hyc commented 4 years ago

If you want to claim electrum-compatible then we should be using their wordlist as-is, no?

knaccc commented 4 years ago

@hyc I'm not sure if anyone was suggesting that it would be beneficial to be "electrum-compatible". The only reason for using the electrum word list is that it contains 2048 words instead of 1626. We've already broken electrum compatibility by having 14 words instead of 12/13, a different type of checksum, and a 'coinflag' applied.

I just checked, and the non-English word lists for BIP39 do not include the word 'satoshi'. So we'd only be messing around with the English wordlist. I'd argue that normal people will not recognize the word 'satoshi', and so the presence of this word slightly hinders the ability of a normal person to write down the seed or communicate it verbally to another.

One could make the argument that someone implementing 14-word Monero seed functionality could easily make a mistake if they did not notice that we had changed the English wordlist slightly. But I think that's a difficult argument to make, since their implementation would not be able to validate seeds generated by other Monero implementations, and it'd be hard to pay enough attention to successfully implement the Reed Solomon algorithm yet miss the implementation notes about the English wordlist being different.

xiphon commented 3 years ago

Pinging @tevador and others interested.
Please double check point 3, let me know if i'm missing something.

Current seed scheme is a two-way conversion, i.e. one can freely get a seed from wallet key on a wish.

Given that https://github.com/tevador/monero-seed PoC is a one-way conversion (i.e. you can't generate a seed from wallet keys):

  1. No way to migrate current wallets to new scheme. All monero users will have to generate new wallets to use new seed scheme.
  2. Requires to store the seed on disk and to load it on wallet startup to provide a way to print wallet seed (seed command).
    Currently we convert wallet key into mnemonic seed on the fly.
  3. I'm also somewhat concerned that it might affect security due to using only 128 instead of 256 bits of entropy. Attack monero-seed scheme Current scheme
    Brute-force ALL seeds 2128 2256
    Brute-force ALL key 2256 2256
    Recover 1 specific key (Pollard's Rho algo) 2128 2128

    * omitted guessing a few wallet birthday bits in monero-seed case

Opinions? Should we consider discussing some other seed scheme?

tobtoht commented 3 years ago

Requires to store the seed on disk and to load it on wallet startup to provide a way to print wallet seed (seed command).

An elegant solution to this problem is to store the mnemonic seed in .keys. This way it will always be available in case the wallet cache is discarded.

omitted guessing a few wallet birthday bits in monero-seed case

Birthday bits are in addition to the 128-bit private key seed.

xiphon commented 3 years ago

An elegant solution to this problem is to store the mnemonic seed in .keys. This way it will always be available in case the wallet cache is discarded.

The point is about the additional logic that looks redundant to me. We do store the keys and we will have to also store the seed basically in plaintext.

PS: yes. Obviously, .keys file is the only possible place to store the seed. Using wallet cache would be a mistake.

Birthday bits are in addition to the 128-bit private key seed.

That's exactly what i mean. You can't just count them in because actual range to brute force will be based on the implementation.

If 3) is a valid concern, a few extra bits barely change anything.

tobtoht commented 3 years ago

basically in plaintext.

As I'm sure you know .keys is encrypted on disk, so I'm not sure what you mean by this. The mnemonic seed would benefit from identical protection as the private spend key, and it can even be encrypted in memory until it is needed similarly to the other keys.

I don't see how storing an additional value in .keys is an issue at all.

If 3) is a valid concern, a few extra bits barely change anything.

Yes, but there are no extra bits. Anyone attempting to brute force all possible spendkeys that can be generated with this seed scheme would just iterate over the 128-bit key seeds directly.

rbrunner7 commented 3 years ago

My thoughts about those issues:

1) is certainly unfortunate from an UX point of view, but I think we should take the long view here. If Monero really is successful as a currency it will probably live on for many years, if not decades, and all the wallets and all the users of the few years that already passed will become a small and therefore more and more unimportant minority over time.

2) does not worry me one bit, frankly. Sometimes UX improvements lead to more effort needed in code, but so what? On other fronts person months are spent, e.g. to make transactions somewhat smaller and verify somewhat faster to improve UX, so surely extending the things stored in the .keys file somewhat should not matter too much. I sneaked in something there for the MMS, without anybody barely noticing, and it was programmed in half a day.

3) Seems to me we are not talking about a key space of 128 bits versus one of 256 bits in isolation, but we are talking about Monero wallets in particular. And here I really wonder whether there is a viable method to even make, say, 1,000,000 attempts, to brute-force your way into a wallet in a reasonable time. How would that work, in detail? Seems to me brute-forcing stands and falls with a fast method to check whether guesses are correct. Is this given here?

tevador commented 2 years ago

I revisited my PoC mnemonic seed and reimplemented it as a C-library. Should be pretty much plug and play and ready to be integrated into simplewallet.cpp.

https://github.com/tevador/polyseed

Some of the improvements I made:

The only concern that remains is the one-way conversion. There is no way around it, it's simply the price to pay for a more compact mnemonic seed. But since we have to keep supporting the 25-word seed anyways, users don't have to generate new wallets. Legacy wallets would still have to input the wallet birthday manually, but eventually (as the blockchain grows), this prompt could be removed as the fraction of outputs created during the old seed scheme becomes negligible (I think this is the point @rbrunner7 was making).

CryptoGrampy commented 1 year ago

Hi @tevador -

It's been nearly a near since we've seen any movement on this topic; do you have any concerns with Polyseed/have there been any issues with its implementation in Feather? Do you think it should be added to GUI/CLI wallets?

tevador commented 1 year ago

I'm not aware of any issues with Polyseed. AFAIK it's still on the roadmap for Seraphis.