-
Notifications
You must be signed in to change notification settings - Fork 312
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 how descriptor checksums are calculated #765
Fix how descriptor checksums are calculated #765
Conversation
If `exclude_hash` is set, we split the input data, and if a checksum already existed within the original data, we check the calculated checksum against the original checksum. Additionally, the implementation of `IntoWalletDescriptor` for `&str` has been refactored for clarity.
`Wallet` stores the descriptors' checksum in the database for safety. Previously, the checksum used was a checksum of a descriptor that already had a checksum. This PR allows for backward-compatibility of databases created with this bug.
c5f63a6
to
e2a4a58
Compare
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.
Concept ACK.. Great job finding this out.. I reproduced the bug by the following method
- Created a descriptor, once with and then without checksum. Calculate checksum manually using
get_checksum()
. - Calculate checksum using
wallet_name_from_descriptor
which calls the sameget_checksum()
function but ensures to exclude the checksum if present in descriptor. - Read the checksum value stored in db after running bdk-cli using w/wo checksum descriptor.
Here's the trial outputs for reference
Master:
desc w checksum: wpkh(032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3)#wc9dk083
get_checksum() : arwnyfm2
wallet name : wc9dk083
get_checksum bytes [97, 114, 119, 110, 121, 102, 109, 50]
wallet name bytes : [119, 99, 57, 100, 107, 48, 56, 51]
checksum in db : [97, 114, 119, 110, 121, 102, 109, 50]
desc w/o checksum: wpkh(032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3)
get_checksum : wc9dk083
wallet name : wc9dk083
get_checksum bytes [119, 99, 57, 100, 107, 48, 56, 51]
wallet name bytes : [119, 99, 57, 100, 107, 48, 56, 51]
checksum in db: [97, 114, 119, 110, 121, 102, 109, 50]
PR 765:
desc w checksum: wpkh(032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3)#wc9dk083
get_checksum : wc9dk083
wallet name : wc9dk083
get_checksum bytes [119, 99, 57, 100, 107, 48, 56, 51]
wallet name bytes : [119, 99, 57, 100, 107, 48, 56, 51]
checksum in db : [119, 99, 57, 100, 107, 48, 56, 51]
desc w/o checksum: wpkh(032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3)
get_checksum : wc9dk083
wallet name : wc9dk083
get_checksum bytes [119, 99, 57, 100, 107, 48, 56, 51]
wallet name bytes : [119, 99, 57, 100, 107, 48, 56, 51]
checksum in db : [119, 99, 57, 100, 107, 48, 56, 51]
Observation:
-
Master is clearly storing wrong checksum in db for desc with checksum data. But it seems master is also storing the wrong checksum in case of descriptor w/o checksum. Check the Master Case 2,
checksum in db
value. I am not sure why this is happening. This means master will forcefully include the checksum in checksum calculation, even if its not there? -
In any case this PR seems to be working as expected, and both
get_checksum
and checksum stored in db is matching withwallet_name_from_descriptor
, so everything seems consistent.
Few comments below on code.
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 reviewed only the first commit for now, but I feel like we need to tell our users about the bug in some way:
- I don't want to silently change the behavior of
get_checksum
- if some users used it the same way we do, they need to implement some way of switching to the new checksums - or just keep using the old ones - On the other hand... exposing a boolean
exclude_hash
is a bit confusing. All the new users, and some of the old ones, don't need to know what'sexclude_hash
is about.
I'm thinking that we might achieve something useful with deprecating old methods, but I'm really not sure... Any ideas?
Rename replacement functions calc_checksum_bytes and calc_checksum
37645ea
to
60057a7
Compare
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.
Thanks @notmandatory for carrying the work.. This looks almost complete and good to go..
tACK 60057a7
Below are few nits and testing suggestions..
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.
ACK 60057a7
@notmandatory Thank you for moving the PR forwards. Looks good to 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.
ACK 648282e
I think this one is ready to merge, but I'm going to hold off until #770 is merged since I think it will be easier to rebase this PR on that one. |
Description
Previously, the methods
get_checksum_bytes
andget_checksum
do not check input data to see whether the input data already has a checksum.This PR does the following:
exclude_hash: bool
flag forget_checksum_bytes
, that excludes the checksum portion of the original data when calculating the checksum. In addition to this, if the calculated checksum does not match the original checksum, an error is returned for extra safety.Wallet
is still backwards compatible with databases created with the "checksum inception" bug.Notes to the reviewers
Thank you.
Changelog notice
Fix the "checksum inception" bug, where we may accidentally calculate the checksum of a descriptor that already has a checksum.
Checklists
All Submissions:
cargo fmt
andcargo clippy
before committingBugfixes:
* [ ] I'm linking the issue being fixed by this PR