-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Electrum misinterprets master extended key (depth 0) as child extended key with depth 3 #3671
Comments
you derived xprv/yprv/zprv at the root level. |
To which spec do you refer by “this” spec? Electrum’s? Is it written down somewhere, outside the Python code? My code perfectly implements BIP 39, and the pertinent portion of BIP 32 for master extended private key generation and serialization. It passes all English and Japanese test vectors, including If Electrum follows a different spec, I would appreciate a reference I could use to implement it properly. Should the “depth” byte be set to FWIW, I searched the Electrum issues for pertinent keywords before I opened a new issue—and just now, again. Also, obviously I found the place in the Electrum code which contains the magic numbers for |
we will release a BIP shortly |
Thanks for your reply. But this only lists the same magic numbers as I found in Electrum’s If I did not have those version numbers, then I would not have obtained “yprv” and “zprv” from the base58check encoding. I did not just slap those on, you know. Now as for The input I feed to to base58check is laid out as such:
That passes the test vectors. |
I think @ecdsa is saying you need to use So your zprv should be derived:
|
yup. I was able to get the same addresses by: > var btc = require('bitcoinjs-lib')
// import your root xprv you gave
> var hd = btc.HDNode.fromBase58('xprv9s21ZrQH143K2XmdMqcWE29L75KLystP5qeMrRh7NJZdKvdRykoR6wNVohA7yUeaRtK2vni2ybAAY7mt8QyAmJDt6EF7f7DhbHFNMit7keL')
// derive m/44'/0'/0' and export as base58check
> hd.deriveHardened(44).deriveHardened(0).deriveHardened(0).toBase58()
'xprv9z7KYqivhqD6FHfsDLbFEPDfWFt6xHzV1j3fG4rHoV4w2ppyd74aY8UwywJb8eqxAoJ7NqiDp1dCsYzicgnGPkhmhbLZkMnWhMwUxa23Uah' And recovering from that. |
Thank you, @dabura667. I will try adding code for this later, if I want to support the Electrum use cases I’d intended. The question then is why Electrum will accept a master extended private key with depth 0, and neither reject it, nor ask the derivation path and follow it (as it does from a BIP39 mnemonic). It will simply spit out entirely different addresses. This is a bug. Neither considering my code nor the new Segwit You wrote whilst I was experimenting with Electrum, and gathering precise reproduction details and screenshots using a test vector from Trezor’s vectors.json. If Electrum will accept both of these and yet generate totally different addresses, then that’s a bug. Following are the exact steps I followed, starting with an empty
|
@dabura667, thank you for the information you provided. I confirmed on my end that the
Now I know affirmatively which depth of key Electrum is expecting; so I can code to that. But if Electrum accepts the master extended key (depth byte |
In addition to previously undocumented features from c912169 and 37defc2, this commit does: - Update the manpage to document new functionality, for full BIP 39 support and rudimentary BIP 32 support. - Add option -j to read passphrase from file. This is principally intended for use with FIFOs in scripts, for generation of test vectors. - Modestly refactor a few parts needed to make all passphrase functionality consistent, and tighten up handling of options in main(). - Refuse to read -k keymat or -j passphrases from a tty. - Add the undocumented -D option, which at present only causes the -A output to include the passphrase (if any). This is for generation of test vectors. - Hide the undocumented -E option behind an undocumented compile-time knob, to prevent potential user funds loss. See spesmilo/electrum#3671. - Add a caveat to the manpage against using the output xprv with Electrum. See again, spesmilo/electrum#3671. - Update the README.md to advertise new functionality.
@ecdsa Thanks for the heads up about writing the BIP. I hope it will be up as soon as possible, please inform the general audience so we can push for a better standard than bip-39. Even the bitcoin core devs agree that bip-39 should be not implemented. |
I agree, this is still a bug. I can enter the
when restoring a wallet from what Electrum calls "master private key" and they are all accepted, generating totally different wallets. From trial it looks like Electrum refers to the second (Account Extended Private Key). (I used the nomenclature from Ian Coleman's implementation.) |
As briefly explained in my commit log at nym-zone/easyseed@c912169:
Expected behaviour
Wallet created from an “xprv”/“yprv”/“zprv” extended master private key matches wallet restored from BIP 39 mnemonic phrase plus appropriate BIP 32 derivation path.
Actual behaviour
Wallet restored from an “xprv”/“yprv”/“zprv” extended master private key generates/contains addresses different from that restored from the mnemonic as aforesaid. This may cause user loss of funds: If a user creates a wallet from an extended master private key, and uses the matching BIP 39 mnemonic phrase as a backup, then the backup will apparently be useless for restoring the wallet.
Example Test Data
The following “steps to reproduce” use this test vector, generated with easyseed:
These can be reproduced with the following command, as of nym-zone/easyseed@c912169:
Other test vectors were tried by me, from the set of official test vectors listed in BIP 39. E.g.:
Mnemonic: “hamster diagram private dutch cause delay private meat slide toddler razor book happy fancy gospel tennis maple dilemma loan word shrug inflict delay length”
Passphrase (Electrum “Extra Words”): “TREZOR”
Extended master private key:
Steps to Reproduce
Create a wallet “test” in Electrum, using the “xprv”, “yprv”, or “zprv” extended master private key.
Create another wallet “test_verify” in Electrum, using the BIP 39 mnemonic with the appropriate derivation path:
m/44'/0'/0'
m/49'/0'/0'
m/84'/0'/0'
(N.b. that I did not expect this to work, because BIP 84 was first published as a draft eleven days ago, on 2017-12-28. It creates a wallet full of old-style “1” addresses, rather than Bech32 “Bravo Charlie” addresses. The other two given derivation paths should certainly work.)Version Information
Tested with Electrum version 3.0.4.
Additional Information
I do not see how this could be a bug in my software. It is remotely possible that I could make a stupendously moronic mistake; but then, my software would not pass the test vectors as it does every
make check
(including “hamster diagram private dutch...” and dozens of other in English and Japanese). I tried to look through the Electrum codebase for some cause; but it is an unfamiliar codebase in an unfamiliar language, and I didn’t see anything obvious at a glance/grep through the BIP39/BIP32 parts oflib/keystore.py
andlib/bitcoin.py
.After entering a BIP 39 mnemonic phrase into Electrum and clicking for the next screen, a bizarre small, blank window popped up. It did not go away, even when the Electrum process exited. I observe this on v3.0.4; I did not observe it on v3.0.3 or previous versions of Electrum, in which I have tested BIP 39 mnemonic entry.
To be clear: I strongly disagree with the nonstandard “xprv”/“yprv”/“zprv”/etc. scheme, which abuses BIP 32 serialization version numbers to convey information which should be contained in the derivation path. The same problem exists with “tpub”/“tprv” in the spec, insofar as testnet addresses also have their own derivation paths. An extended master private key (or public key) is not tied to only one type of address. However, I preliminarily implemented this in the hope of helping users adopt Segwit with the most popular userfriendly light client—for the good of users (lower fees), and for the good of the network.
The text was updated successfully, but these errors were encountered: