-
Notifications
You must be signed in to change notification settings - Fork 273
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
Unneeded manual alignment in *_context_create
#529
Comments
The code just writes the size of the allocated buffer before the actual buffer. So we add |
I do see now that the code doesn't handle failed allocation, we should add: if ptr.is_null() { handle_alloc_error(layout); } I can PR this in the weekend if no one else gets to it before |
OK, that explains it but why do we allocate more rather than calling |
That would require us to keep the flags around, so requires bigger allocation anyway |
There's also Previous idea that I realized doesn't workThis doesn't work for dynamic linking since the dynamically linked library might have a context of different size. But I checked the function and it actually returns If we're willing to incur the cost of checking the code on each update maybe consider this approach:
If the code ever becomes dependent on flags we can probably reimplement it in Rust as This gets rid of the additional allocation. People can store Also note that we could use this technique to get the actual alignment and not hard-code 16 (which is probably overkill and we likely only need 8 on current platforms). @apoelstra I'm curious what do you think about this since it's somewhat big change. |
All these functions did depend on the size until quite recently, and when they did, The size of these objects was also multiple megabytes, too much to put on the stack. As you note, the flags are not really used now ... so what purpose do they serve? That is part of a larger issue, #346. Having said all this I am very doubtful that we'll return to a "massive context object whose size is runtime-dependent" model in the next several years. So given that, I am really tempted by your idea and I think I will try to explore it. |
Oh, interesting, I'm curious what made upstream change from those complex things to the simple implementation.
If we're going to do this we must make sure dynamically linking a library with different context layout is impossible or fall back to the current version if dynamic linking is enabled. I was also thinking about providing const constructor but I doubt it's a good idea. |
They moved to a model where they precompute tables at compile-time rather than run-time. (And you can configure their size at compile-time; I think the This does eliminate the case where somebody might have limited flash but lots of RAM, but it dramatically simplifies the context object management (and in fact, eliminates the need for any context object at all, in much of the library, strictly speaking). |
Because upstream libsecp256k1 has no released versions this is already pretty-much guaranteed UB to try to dynamically link whatever random shit somebody might have in their /usr/lib. I don't know if we can make it impossible (we should explore that) but we're not making it any less safe by changing our allocation strategy.
The context object now only contains aux data for rerandomization, which is only used by signing code. I think a const constructor would be fine. |
There are still places I find surprising that they need it. For instance |
…ator 8b17fc0 call the alloc error handle if we get NULL from the allocator (Elichai Turkel) Pull request description: Found that this was missing in this discussion: #529 (comment) It is documented here that it returns a NULL on memory exhaustion: https://doc.rust-lang.org/alloc/alloc/trait.GlobalAlloc.html#tymethod.alloc And you can see that this is called in this example: https://doc.rust-lang.org/alloc/alloc/fn.alloc.html Docs for the handle itself: https://doc.rust-lang.org/alloc/alloc/fn.handle_alloc_error.html ACKs for top commit: apoelstra: ACK 8b17fc0 Kixunil: Good argument, ACK 8b17fc0 Tree-SHA512: 4b8f79ab5f691cb92621a314ceb8556c26fa7e159de359697b766043a0269e1ecf9746e6d4bfd5b45f18bccaff435c1fff491168b8bb77459ae849c38664d563
All the API functions still "need" it, as a form of future-proofing. This library is in an awkward state right now because upstream has de-facto eliminated the need for context objects in all non-signing contexts, but kept context arguments in all the APIs in case they want to use them one day in the future. We have not decided if we want to follow, or if we should just eliminate the context objects from our APIs. Separately but relatedly, we haven't decided what the best approach to signing contexts is, which is the subject of #346 . |
Ah, so theoretically we could pass null or dangling pointers into those APIs? If yes that'd make
Didn't we conclude to use TLS with a fallback to a "lock" that doesn't re-randomize on contention? |
No, the code does check that they're non-null (and may even dereference them). But we can pass a static context or even generate one on-the-fly with no capabilities (which will be essentially free, especially if we do it on the stack).
Yeah, I guess so :) so maybe we can start moving forward. |
Wouldn't it break if the library changes to require verification capability? FTR, the context size is now 208B on x86_64 which shouldn't cause problems. |
Yeah, but in that case we'll figure something out. It will only break when we upgrade the copy of the library that we vendor.
Nice. Though the actual contents include function pointers so I'm doubtful we'll be able to make a const contsructor for it. |
With all these changes I wonder if we should fail compilation if someone tries to link
Sucks but since we already make a bunch of assumptions maybe it wouldn't be too bad to just mirror the C struct and fill it from Rust? |
I don't think anything we're discussing makes this more dangerous, but regardless, I think we might actually be safe because we rename all the symbols that we use.
If we can mirror function pointers (I'm never sure what the FFI supports) then yeah, for sure we can do this. |
We have a feature to not rename them 🤷♂️ Maybe it should be renamed to say
We can, if we couldn't, the library would already not work. :) |
IMO this is way overkill. It's not even a feature, it's a
Hah, good point. |
BTW I opened #538 so we can move discussion to there (or perhaps we should have yet another issue specifically about trying to prevent people from replacing our vendored library with a different incompatible one) |
Honestly, it wasn't to me. I didn't even know |
For sure -- wherever we document that |
There seems to be unneeded code for manual alignment in the
*_context_create
function.alloc
already returns memory aligned toALIGN_TO
. Am I missing something?The text was updated successfully, but these errors were encountered: