-
Notifications
You must be signed in to change notification settings - Fork 416
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
fix leading zero and add test #161
Conversation
Correction of key length with initial zero The length of the child private key must be at least 32
@klim0v thanks! Kind of swamped today but hope to get to this one by tomorrow. |
@klim0v the decred code for this is identical to our original code (it was just copied from here of course). |
Yes, I can help you do this. |
@jcvernaleo |
@klim0v sorry about that (and thanks for the reminder). Totally flake out on this. Could you just squash it and it will be good to go. Then I think you should make a matching PR on decred too. |
This is technically accurate, however, I will point out that fixing it means it will break anything that has derived keys using the existing code and therefore it is a breaking API change that should be accompanied with a major version bump. This change can and will suddenly cause people to be unable to derive the private keys they need to spend any coins which pay to public keys that were originally derived under the current code. I'm really not sure what type of versioning the project is using nowadays, but this change could easily make coins unspendable for some consumers. This is a decision for the maintainers of the project now, but I suspect this change should be rejected as is, despite it being technically correct, due to that. A likely reasonable solution would be to expose the existing derivation semantics via a legacy function and make sure to loudly warn about the difference.
This fix can't be deployed in Decred as is because of the aforementioned issue. The primary wallet software in widespread use derives keys based on the current code, so, any change in this regard would absolutely make people lose access to their coins which is obviously not acceptable. |
Okay, definitely do not want to break things for existing usage. @klim0v what was the initial motivation for this? |
The motivation was certainly because the existing code does not conform with the BIP32 specification In particular the spec defines the function So, the fix is indeed technically accurate, as I stated above, however, changing it also has the aforementioned problem of breaking people who have secured coins with the the non-conformant derivation code. |
The reason for this correction was the fact that our organization https://github.com/MinterTeam creates blockchain services, in which the creation of addresses is similar to the algorithm in ethereum. When I wrote the SDK for golang using transaction signing, it turned out that in about 1% of cases, the addresses created from the seed phrases do not match the addresses received in the SDK written in other languages. For this I used libraries such as:
which used your library to create the master key. I agree with @davecgh that this fix, which is not part of the major version, could lead to the loss of wallets. But at the same time I would like to nevertheless restore the technical correctness of the algorithm, and at least indicate this inaccuracy in the description. Otherwise, it will lead to conflicts in other new projects. |
Hmmm, okay, so I guess we have a few options here (and if I missed anything, someone please correct me):
|
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.
Just requesting changes here so we don't accidentally merge while trying to decide the best way forward. Not sure if there is a more elegant way to do that.
It looks like BIP32 was updated to add a 3rd test vector specifically for this case. Depending on how this proceeds, I would suggest adding that new 3rd test vector to |
Thanks for the link. I added my test to TestBIP0032Vectors. Do not close PR, please. I will contact bitcoin/bips and suggest that they add my test to the documentation. |
In the library https://github.com/btcsuite/btcutil and https://github.com/decred/dcrd all the tests that are listed here pass successfully, but there is an error on my case. Seed: "57fb1e450b8afb95c62afbcd49e4100d6790e0822b8905608679180ac34ca0bd45bf7ccc6c5f5218236d0eb93afc78bd117b9f02a6b7df258ea182dfaef5aad7", want pub: "xpub6CpsfWjghR6XdCB8yDq7jQRpRKEDP2LT3ZRUgURF9g5xevB7YoTpogkFRqq5nQtVSN8YCMZo2CD8u4zCaxRv85ctCWmzEi9gQ5DBhBFaTNo", want priv: "xprv9yqXG1Cns3YEQi6fsCJ7NGV5sHPiyZcbgLVst61dbLYyn7qy1G9aFtRmaYp481ounqnVf9Go2ymQ4gmxZLEwYSRhU868aDk4ZxzGvqJVH". The correction and discussion can be found here btcsuite/btcutil#161
A lot of packages use your bip32 implementation 😔 |
So does anyone have thoughts on the three sets of options I posted above? |
As I said before, I think the right approach is to fix it, offer a legacy version which retains the old behavior (internally you just abstract the core logic into a function with a flag to strip the leading zeros on the child key or not and then call it with true/false from the respective exported function), ensure the major version is bumped, and loudly warn consumers about the change and make it clear that if they have created seeds and derivations using the existing code they must use the legacy version. However, for all new seeds, they need to use the new version. |
Question for @Roasbeef This code is used in all versions of LND as of current, correct? |
I have added an optional parameter for this. We can make another wrapper for him. In the next major version, already do a wrapper with a check already for a false value |
I think it can be added to the new release without changing the major version |
…(i uint32, fixLeadingZeroBug ...bool) method Use the 2nd parameter to fix the bug with leading zeros. This change was made as an optional parameter in order to maintain backward compatibility and avoid losing wallets created before fixing this bug.
…ol) method for tests and examples
Yeah, |
// Use the 2nd parameter to fix the bug with leading zeros. This change was made | ||
// as an optional parameter in order to maintain backward compatibility and avoid | ||
// losing wallets created before fixing this bug. | ||
func (k *ExtendedKey) Child(i uint32, fixLeadingZeroBug ...bool) (*ExtendedKey, 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.
This solution strikes me as being...inelegant. With this for the foreseeable future, the API is forced to carry a parameter that conditionally fixes an issue of spec compliance. This isn't backwards compatible as the comment indicates since this is actually itself a breaking API change, so it warrants a v2
major version bump IMO.
Another option would be to add a new method that always applies the leading zero fix, with the existing public one calling that with the fix toggled off.
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.
This solution strikes me as being...inelegant. With this for the foreseeable future, the API is forced to carry a parameter that conditionally fixes an issue of spec compliance. This isn't backwards compatible as the comment indicates since this is actually itself a breaking API change, so it warrants a
v2
major version bump IMO.
Can you explain why this cannot be considered backward compatible? This parameter is optional and does not correct the default error if it is absent.
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.
If someone created an interface in their app under the assumption that ExtendedKey fulfills it, and their interface has the call signature of Child(i uint32) (*TheirInterface, error)
suddenly ExtendedKey no longer fulfills it.
Therefore it is breaking.
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've come around to this approach, if you can update this PR before #182 does, I think it can land.
Something like https://golang.org/pkg/testing/quick/#CheckEqual can likely be used to find any other divergences across the various BIP 32 implementations. |
Of course the upside of not doing a new major version (which requires users to manually switch over as there would be a new sub-directory), is that if the API is broken, they'll be forced to make a decision when they upgrade, vs somehow hearing about the new more compatible API. |
Should be able to get away with only an internal version bump for aezeed since there's no modification to the serialization/interpretation of the internal payload. |
Also @GuiltyMorishita might want to look at this too. This bug will affect Ginco wallet compatibility with other wallets. |
@junderw Thank you for mentioning me. Ginco Wallet does not use the package, so there is no problem. |
@klim0v is there still anything useful in this PR, or can we close it ? |
As far as I remember, this issue has been fixed in #182. We now have the |
Correction of key length with initial zero
The length of the child private key must be at least 32