-
Notifications
You must be signed in to change notification settings - Fork 37.7k
fuzz: add ConstructPubKeyBytes util function #28361
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
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. 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. |
Maybe add There's another behavior change here, probably a good one: while generating N keys, they're now completely different. Previously we would only change the last byte to make them unique. |
No, they are not guaranteed to. Now they will consume bytes for their whole length, which may exhaust the available bytes faster and thus result in all-zeros and also bloat the fuzz inputs git folder. Previously they consumed no additional bytes. Not sure why this is called a refactor, when everything is changed. |
Ah, that's not good. |
bc5b393
to
f4a51ac
Compare
That was an oversite on my part. I've updated the function to use the buffer as before, so the first commit should be just a refactor now. I also split out adding the missing hybrid pubkey byte into it's own commit. |
Done! The first commit should now be strictly a refactor. |
f4a51ac
to
ab94167
Compare
CI failure seems unrelated to the changes here unless I'm missing something. @hebasto ? |
ACK ab94167 From libsecp256k1: /** Prefix byte used to tag various encoded curvepoints for specific purposes */
#define SECP256K1_TAG_PUBKEY_EVEN 0x02
#define SECP256K1_TAG_PUBKEY_ODD 0x03
#define SECP256K1_TAG_PUBKEY_UNCOMPRESSED 0x04
#define SECP256K1_TAG_PUBKEY_HYBRID_EVEN 0x06
#define SECP256K1_TAG_PUBKEY_HYBRID_ODD 0x07 We now cover all of these.
|
Restarted. |
Still failing but with a different functional test failure now, which seems to be related to timeouts. |
It's green now. |
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.
lgtm, all good.
Though, refactor
is still wrong, because the fuzz input format is changed.
Generally I don't think the refactor
label makes any sense for (unit) tests, because end users in production are never affected by test-only changes.
ab94167
to
9bb2627
Compare
I removed it from the title, but feel that it's still useful on the commit message. Using the refactor label, to me, is about communicating intent to the reviewer. The first commit in this PR was not meant to change behavior, and calling it a refactor made it more obvious to reviewers that some behavior had in fact changed. Adding |
@@ -14,6 +14,19 @@ | |||
|
|||
#include <memory> | |||
|
|||
std::vector<uint8_t> ConstructPubKeyBytes(FuzzedDataProvider& fuzzed_data_provider, Span<const uint8_t> byte_data, const bool compressed) noexcept |
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.
nit: Could name it pk_data
over byte_data
?
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 prefer byte_data
because we are reading in an array of bytes and turning it into pk_data
by adding a prefix byte to indicate compressed or uncompressed. At the moment we read it in, it is not pk_data
. We turn it into pk_data
(i.e. a byte array with the correct prefix), and then that is returned and can be serialized or turned into a CPubKey
object.
|
Today, this code only has one spot where it needs well-formed pubkeys, but future PRs will want to reuse this code. Add a function which creates a well-formed byte array that can be turned into a pubkey. It is not required that the pubkey is valid, just that it can be recognized as a compressed or uncompressed pubkey. Note: while the main intent of this commit is to wrap the existing logic into a function, it also switches to `PickValueFromArray` so that we are only choosing one of 0x04, 0x06, or 0x07. The previous code, `ConsumeIntegralInRange` would have also picked 0x05, which is not definied in the context of compressed vs uncompressed keys. See https://bitcoin.stackexchange.com/questions/57855/c-secp256k1-what-do-prefixes-0x06-and-0x07-in-an-uncompressed-public-key-signif for more details.
9bb2627
to
1580e3b
Compare
@MarcoFalke squashed and removed the refactor label since we will no longer be creating pubkeys with an |
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.
Seems fine to remove 5
. The reason to have it was to also create "invalid" data and see if it causes a crash. But no strong opinion, as it may be covered by other fuzz tests already.
That doesn't match the comment, Going forward, I think it's better to have a function just for creating well-formed pubkey data (i.e. correct prefixes) and then use random or invalid data for cases where we actually want to test for that. |
That makes sense, but since we previously covered |
In theory malformed data can also be covered by the outer wrapper, see [&] {
// Insert byte vector directly to allow malformed or unparsable scripts
r_script.insert(r_script.end(), buffer.begin(), buffer.begin() + fuzzed_data_provider.ConsumeIntegralInRange(0U, MAX_BUFFER_SZ));
}, Absent data, I think anything is fine here. I just wanted to clarify that what you are changing is intentional. |
I'm inclined to leave this pull as is, and if we find there is a real need for mutating with an invalid prefix inside the "push multisig" case, we address it in a follow-up. The way things are written now seems more clear to me: we have a case for sending random bytes to |
@MarcoFalke @Sjors can you let me know if this looks good as-is (where some things can be addressed in follow-ups), or if you'd like to see more changes in this PR before merging? |
Nothing blocking, but haven't re-reviewed the code yet. |
ping @Sjors @MarcoFalke |
ACK 1580e3b |
1580e3b fuzz: add ConstructPubKeyBytes function (josibake) Pull request description: In bitcoin#28246 and bitcoin#28122 , we add a `PubKeyDestination` and a `V0SilentPaymentsDestination`. Both of these PRs update `fuzz/util.cpp` and need a way to create well-formed pubkeys. Currently in `fuzz/util.cpp`, we have some logic for creating pubkeys in the multisig data provider. This logic is duplicated in bitcoin#28246 and duplicated again in bitcoin#28122. Seems much better to have a `ConstructPubKeyBytes` function that both PRs (and any future work) can reuse. This PR introduces a function to do this and has the existing code use it. While the purpose is to introduce a utility function, the previous multisig code used `ConsumeIntegralInRange(4, 7)` which would have created some uncompressed pubkeys with the prefix 0x05, which is incorrect (see https://bitcoin.stackexchange.com/questions/57855/c-secp256k1-what-do-prefixes-0x06-and-0x07-in-an-uncompressed-public-key-signif) tldr; using `PickValueFromArray` is more correct as it limits to the set of defined prefixes for compressed and uncompressed pubkeys. ACKs for top commit: Sjors: ACK 1580e3b Tree-SHA512: c87c8bcd1f6b3a97ef772be93102efb912811c59f32211cfd531a116f1da8a57c8c6ff106b34f2a2b88d8b34fb5bc30d9f9ed6d2720113ffcaaa2f8d5dc9eb27
In #28246 and #28122 , we add a
PubKeyDestination
and aV0SilentPaymentsDestination
. Both of these PRs updatefuzz/util.cpp
and need a way to create well-formed pubkeys. Currently infuzz/util.cpp
, we have some logic for creating pubkeys in the multisig data provider. This logic is duplicated in #28246 and duplicated again in #28122. Seems much better to have aConstructPubKeyBytes
function that both PRs (and any future work) can reuse.This PR introduces a function to do this and has the existing code use it. While the purpose is to introduce a utility function, the previous multisig code used
ConsumeIntegralInRange(4, 7)
which would have created some uncompressed pubkeys with the prefix 0x05, which is incorrect (see https://bitcoin.stackexchange.com/questions/57855/c-secp256k1-what-do-prefixes-0x06-and-0x07-in-an-uncompressed-public-key-signif)tldr; using
PickValueFromArray
is more correct as it limits to the set of defined prefixes for compressed and uncompressed pubkeys.