-
Notifications
You must be signed in to change notification settings - Fork 38.7k
wallet: Fix Char as Bool in Wallet #16572
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
Conversation
|
Seems like an improvement, any idea why this was a char in the first place (or how it came to be)?
Wait, this metadata is never part of the transaction hash right? |
|
It seems like it is just old/crufty. It was previously proposed by @ryanofsky to be removed (dummied out), but that went nowhere. #9351 Keeping the distinction seems OK to me, but the consistency issue should be fixed in any case. The metadata isn't a part of the transaction hash, but it could be a part of the hash (like a siphash, not a crypto hash) of the object itself, e.g., for storing in a map. |
|
Concept ACK There's also this which I never got why it was a bitcoin/src/wallet/coinselection.cpp Line 173 in e5fdda6
|
|
Actually there is a reason for that one! Vec bool is typically compacted, so it's probably slower running because of masking. Maybe worth profiling to find out! |
|
From a march 2011 mail from Satoshi to me about how the wallet tracks unspent outputs: So I guess the reason was indeed some worry about the std::vector weirdness (it's special cased to be bitbacked). |
|
Hm; may be worth it to go ahead and modify these locations to use Would require some profiling to ensure that there isn't a regression. The only place that is using |
|
Gotta love the unexpected history lessons. :) |
Why? Unless you can demonstrate specific performance improvements, where the (possible) compaction causes bottlenecks, I strongly disagree that this is a reason to go around refactoring things. From a developer angle |
|
Ah; I don't suspect there's a performance reason to modify them, but if there's general concern for surprising behavior with the In any case, this is a bit of a side-quest from the scope of this PR. |
What kind of surprising behavior, really? the implementation might be different but as far as I know, the "API contract" is exactly the same? |
|
I think the only surprising thing about it is that you can't cast a pointer to the data to a char pointer and expect any consistent representation of the data... which you shouldn't be doing anyway, but I think the early codebase did stuff like that. |
|
The main one is the data pointer to a bool pointer. There are a few other differences:
|
|
Code review ACK 2dbfb37 I checked that fFromMe is only used as a bool. I also checked bools and chars are being serialized in exactly the same way so this does not change any behavior. |
FWIW this works fine here … (but maybe it's a gcc-ism?) #include <iostream>
#include <vector>
int main() {
std::vector<bool> test;
test.push_back(false);
test.push_back(true);
test.push_back(false);
for (auto const &x: test) {
std::cout << x << std::endl;
};
return 0;
} |
|
@laanwj Note that the The gotcha: Also note that it is implementation-defined if any space efficiency optimisations are done. |
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
meshcollider
left a comment
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.
Regardless of the above discussion on vectors, this change itself looks safe to me, and does make things more sensible IMO.
Code review ACK 2dbfb37
(Your commit isn't linked to your GitHub account btw Jeremy)
2dbfb37 Fix Char as Bool in interfaces (Jeremy Rubin) Pull request description: In a few places in src/wallet/wallet.h, we use a char when semantically we want a bool. This is kind of an issue because it means we can unserialize the same transaction with different fFromMe flags (as differing chars) and evaluate the following section in wallet/wallet.cpp ```c++ if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) { wtx.fFromMe = wtxIn.fFromMe; fUpdated = true; } ``` incorrectly (triggering an fUpdated where both fFromMe values represent true, via different chars). I don't think this is a vulnerability, but it's just a little messy and unsemantic, and could lead to issues with stored wtxIns not being findable in a map by their hash. The serialize/unserialize code for bool internally uses a char, so it should be safe to make this substitution. NOTE: Technically, this is a behavior change -- I haven't checked too closely that nowhere is depending on storing information in this char. Theoretically, this could break something because after this change a tx unserialized with such a char would preserve it's value, but now it is converted to a ~true~ canonical bool. ACKs for top commit: achow101: Code review ACK 2dbfb37 meshcollider: Code review ACK 2dbfb37 Tree-SHA512: 8c0dc9cf672aa2276c694facbf50febe7456eaa8bf2bd2504f81a61052264b8b30cdb5326e1936893adc3d33504667aee3c7e207a194c71d87b3e7b5fe199c9d
Yes, agree, sorry it got derailed. Posthumous ACK 2dbfb37. This change is the right way around, I was arguing against going |
2dbfb37 Fix Char as Bool in interfaces (Jeremy Rubin) Pull request description: In a few places in src/wallet/wallet.h, we use a char when semantically we want a bool. This is kind of an issue because it means we can unserialize the same transaction with different fFromMe flags (as differing chars) and evaluate the following section in wallet/wallet.cpp ```c++ if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) { wtx.fFromMe = wtxIn.fFromMe; fUpdated = true; } ``` incorrectly (triggering an fUpdated where both fFromMe values represent true, via different chars). I don't think this is a vulnerability, but it's just a little messy and unsemantic, and could lead to issues with stored wtxIns not being findable in a map by their hash. The serialize/unserialize code for bool internally uses a char, so it should be safe to make this substitution. NOTE: Technically, this is a behavior change -- I haven't checked too closely that nowhere is depending on storing information in this char. Theoretically, this could break something because after this change a tx unserialized with such a char would preserve it's value, but now it is converted to a ~true~ canonical bool. ACKs for top commit: achow101: Code review ACK 2dbfb37 meshcollider: Code review ACK 2dbfb37 Tree-SHA512: 8c0dc9cf672aa2276c694facbf50febe7456eaa8bf2bd2504f81a61052264b8b30cdb5326e1936893adc3d33504667aee3c7e207a194c71d87b3e7b5fe199c9d
In a few places in src/wallet/wallet.h, we use a char when semantically we want a bool.
This is kind of an issue because it means we can unserialize the same transaction with different fFromMe flags (as differing chars) and evaluate the following section in wallet/wallet.cpp
incorrectly (triggering an fUpdated where both fFromMe values represent true, via different chars).
I don't think this is a vulnerability, but it's just a little messy and unsemantic, and could lead to issues with stored wtxIns not being findable in a map by their hash.
The serialize/unserialize code for bool internally uses a char, so it should be safe to make this substitution.
NOTE: Technically, this is a behavior change -- I haven't checked too closely that nowhere is depending on storing information in this char. Theoretically, this could break something because after this change a tx unserialized with such a char would preserve it's value, but now it is converted to a
truecanonical bool.