Skip to content

PoC: Add hazmat module (exposing scalar, point)#1635

Open
theStack wants to merge 2 commits into
bitcoin-core:masterfrom
theStack:add_hazmat_module
Open

PoC: Add hazmat module (exposing scalar, point)#1635
theStack wants to merge 2 commits into
bitcoin-core:masterfrom
theStack:add_hazmat_module

Conversation

@theStack
Copy link
Copy Markdown
Contributor

@theStack theStack commented Nov 8, 2024

This PR adds a "hazmat" [1] module for accessing internal data structures and functions (scalar and point for now), with the idea that other libraries could build on top of that. The implementation is inspired by secp256k1-zkp/#153, but aims to provide data types that can be allocated on the stack instead of the heap, as it seems to be significantly simpler from a user perspective if the burden of dynamic memory management can be avoided. The approach to achieve this is by using a "shell type" with fixed size and alignment that hosts the underlying structure not visible to the user [2], eg for scalar:

typedef union {
    unsigned char data[32];
    uint64_t align8; /* ensure alignment on 8-bytes boundaries */
} secp256k1_hazmat_scalar;

Without the alignment enforcing dummy, the compiler emits warnings like "warning: cast from 'const secp256k1_hazmat_scalar *' to 'secp256k1_scalar *' increases required alignment from 1 to 8 [-Wcast-align]" when the public type is converted to the underlying internal type via casting. This admittedly looks a bit fishy and I'm not sure if this is even standard-compliant C89, so would appreciate feedback particularly on that.

For exposing the ge/gej types, a "smart" point object is used that stores the result in jacobi coordinates together with a "z-is-one" flag and converts to affine coordinates when needed (which is trivial by simply assigning x/y if that flag is set). For multiplication with the generator point, a secp256k1 context object is needed, as otherwise it wouldn't be possible to take use of the optimized and more secure variant.

See the added example for how this module could be used in practice.

For further open questions, see the earlier writeup https://gist.github.com/theStack/0893258c3aba91c28539b9334d2e0608.

[1] ="hazardous material"; this terminology origins in Python's pyca/cryptography library, see https://cryptography.io/en/latest/hazmat/primitives/ ("You should ONLY use it if you’re 100% absolutely sure that you know what you’re doing because this module is full of land mines, dragons, and dinosaurs with laser guns.")
[2] see e.g. https://fastcompression.blogspot.com/2019/01/opaque-types-and-static-allocation.html

ViniciusCestarii added a commit to ViniciusCestarii/bitcoin that referenced this pull request Jan 25, 2026
Expose internal functions by incorporating changes from bitcoin-core/secp256k1#1635 to make them available.
@qatkk
Copy link
Copy Markdown

qatkk commented Jan 30, 2026

tACK 1123e35

  • I ran some out-of-tree benchmarks on the scalar APIs of hazmat module using the same initializers and structure as bench_internal. As expected, hazmat was consistently slower, with the gap increasing for larger or denser scalars. From what I can tell, this is due to stricter boundaries and reduced inlining rather than allocation behavior, since both hazmat and internal APIs are allocation-free for the scalars in the test. This isn’t meant as a performance critique — just an observation in case it’s useful context. It might be worth briefly noting in the PR description that this PoC isn’t targeting speed, so readers don’t infer that from the benchmarks.
  • I also reproduced the warning mentioned in the description (on macOS M1). Just confirming that I see the same behavior on my side in case that’s helpful.
    One small question from my side: does this PoC change any assumptions about how scalars are intended to be passed or stored across API boundaries? I want to make sure I’m understanding the intended usage correctly.

Happy to share the benchmark code or numbers if that would be useful.

ViniciusCestarii added a commit to ViniciusCestarii/bitcoin that referenced this pull request Mar 5, 2026
Expose internal functions by incorporating changes from bitcoin-core/secp256k1#1635 to make them available.
ViniciusCestarii added a commit to ViniciusCestarii/bitcoin that referenced this pull request Mar 5, 2026
Expose internal functions by incorporating changes from bitcoin-core/secp256k1#1635 to make them available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants