-
Notifications
You must be signed in to change notification settings - Fork 52
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
Add C++ wrapper class in minisketch.h header #28
Conversation
871c297
to
bcf1bfb
Compare
Great, thanks! |
Doesn't compile for me:
|
bcf1bfb
to
b4d35cd
Compare
@naumenkogs Oops, forgot to test that function. Fixed. |
How to safely use it? I remember minisketch_create could return nullptr in some cases. |
b4d35cd
to
021dd09
Compare
I added an operator bool. So you can use Minisketch minisketch = Minisketch::CreateFP(...);
if (!minisketch) { ... } |
{ | ||
assert(GetSerializedSize() == obj.size()); | ||
minisketch_deserialize(m_minisketch.get(), obj.data()); | ||
return *this; |
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.
Why does this have to return anything if it's called on a sketch instance?
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.
It's so that you can chain operations. E.g. auto vec = Minisketch::CreateFP(...).Deserialize(v).Add(x).Add(y).Merge(z).Serialize();
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 assume this is going to be safe even if the instance evaluates to false
due to implementation issue nullptr?
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 added a Minisketch::SupportedImplementation()
to detect ahead of time which configurations are legal. You shouldn't call Minisketch::CreateFP()
or the Minisketch
constructor for unsupported combinations.
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.
Strong concept ACK. Using an RAII object as the interface is far safer.
include/minisketch.h
Outdated
return *this; | ||
} | ||
|
||
/** Decode this sketch into the result vector, which must have a size equal to the maximum allowed elements. */ |
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.
must have a size equal to the maximum allowed elements
This doesn't seem exactly true. I think minisketch_decode
will return -1 if result.size()
is too small, but it's allowed to be larger (and will be shrunk at the end by result.resize()
. Perhaps the comment should be "must have a size at least as large as the maximum allowed elements"?
For my own understanding: is this requirement to avoid having to reallocate the vector, which would mean this would no longer be 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.
This doesn't seem exactly true. I think minisketch_decode will return -1 if result.size() is too small, but it's allowed to be larger (and will be shrunk at the end by result.resize()
Yes, that's correct. But I don't see how that's in conflict with the comment.
Perhaps the comment should be "must have a size at least as large as the maximum allowed elements"?
No, that'd be wrong. If you make it larger than the maximum number of elements you want, you may get more.
For my own understanding: is this requirement to avoid having to reallocate the vector, which would mean this would no longer be noexcept?
No, just to avoid redundancy. The size of what you want is already passed by the size of the vector you provide, no need to provide it a second time.
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.
Oh, I think I see your confusion. It is intended to mean "You should pass in a vector with a size equal to the maximum number of elements you the caller allow it to return". "Allowed" is maybe not the best term here?
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.
Sorry, yes I was confused by who was allowing who! I'd usually expect the interface to document what the client is allowed to do.
I don't have a great suggestion for changing this. Perhaps something like "Decode up to result.size() elements from the sketch. Will fail if result is not large enough to hold all sketch elements." but I'm not sure if that captures everything.
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 changed the comments a bit.
021dd09
to
a570de2
Compare
I'm not an expert on C++ wrappers, but I've been using this new code for weeks now in Erlay, and the API seems correct. |
#include <stdint.h> | ||
#include <stdlib.h> | ||
#include <unistd.h> | ||
|
||
#ifdef __cplusplus | ||
# if __cplusplus >= 201103L |
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 never seen preprocessor directives nested like this (and didn't realise that whitespace was permitted between the #
and the directive). This makes it so much clearer to see the scope of the #if
s. Really nice 👍
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.
We do have a few examples in the Bitcoin Core codebase, try:
git grep '^# ' $(find -name '*.[ch]' -o -name '*.cpp')
Light review ACK a570de2 |
a570de2
to
8048150
Compare
New comments are clearer to me. Thanks! |
This provides a safer API for use within C++ code. It's just a headers-only wrapper around the C API, so it does not introduce any further binary compatibility concerns.