2f4546ce56 test: add --log option to display tests execution (furszy)
95b9953ea4 test: Add option to display all available tests (furszy)
953f7b0088 test: support running specific tests/modules targets (furszy)
0302c1a3d7 test: add --help for command-line options (furszy)
9ec3bfe22d test: adapt modules to the new test infrastructure (furszy)
48789dafc2 test: introduce (mini) unit test framework (furszy)
9cce703863 refactor: move 'gettime_i64()' to tests_common.h (furszy)
Pull request description:
Early Note:
Don’t be scared by the PR’s line changes count — most of it’s just doc or part of the test framework API.
Context:
Currently, all tests run single-threaded sequentially and the library lacks the ability to specify which test (or group of tests) you would like to run. This is not only inconvenient as more tests are added but also time consuming during development and affects downstream projects that may want to parallelize the workload (such as Bitcoin-Core CI).
PR Goal:
Introduce a lightweight, extensible C89 unit test framework with no dynamic memory allocations, providing a structured way to register, execute, and report tests. The framework supports named command-line arguments in `-key=value` form, parallel test execution across multiple worker processes, granular test selection (selecting tests either by name or by module name), and time accumulation reports.
The introduced framework supports:
* `-help` or `-h`: display list of available commands along with their descriptions.
* `-jobs=<num>`: distribute tests across multiple worker processes (default: sequential if 0).
* `-target=<name>` or `-t=<name>`: run only specific tests by name; can be repeated to select multiple tests.
* `-target=<module name>`, `-t=<module>` Run all tests within a specific module (can be provided multiple times)
* `-seed=<hex>`: set a specific RNG seed (defaults to random if unspecified).
* `-iterations=<n>`: specify the number of iterations.
* `-list_tests`: display list of available tests and modules you can run.
* `-log=<0|1>`: enable or disable test execution logging (default: 0 = disabled).
Beyond these features, the idea is to also make future developments smoother, as adding new tests require only a single entry in the central test registry, and new command-line options can be introduced easily by extending the framework’s `parse_arg()` function.
Compatibility Note:
The framework continues accepting the two positional arguments previously supported (iterations and seed), ensuring existing workflows remain intact.
Testing Notes:
Have fun. You can quickly try it through `./tests -j=<workers_num>` for parallel execution or `./tests -t=<test_name>` to run a specific test (call `./tests -print_tests` to display all available tests and modules).
Extra Note:
I haven't checked the exhaustive tests file so far, but I will soon. For now, this only runs all tests declared in the `tests` binary.
Testing Results: (Current master branch vs PR in seconds)
* Raspberry Pi 5: master \~100 s → PR \~38 s (5 jobs)
* MacBook Pro M1: master \~30 s → PR \~10 s (6 jobs)
ACKs for top commit:
theStack:
re-ACK 2f4546ce56
real-or-random:
ACK 2f4546ce56
hebasto:
ACK 2f4546ce56.
Tree-SHA512: 85ca2cbb620b84b35b353d5d4cf093c388fc3851ca405eeb0e458f8fa72b60534bccd357c7edabf8fc9aa93d9ad0a6fbac3dd5c4d5f9dfdf4d8701a9834755b9
Add support for specifying single tests or modules to run via the
"--target" or "-t" command-line option. Multiple targets can be
provided; only the specified tests or all tests in the specified
module/s will run instead of the full suite.
Examples:
-t=<test name> runs an specific test.
-t=<module name> runs all tests within the specified module.
Both options can be provided multiple times.
Lightweight unit testing framework, providing a structured way to define,
execute, and report tests. It includes a central test registry, a flexible
command-line argument parser of the form "--key=value" / "-k=value" /
"-key=value" (facilitating future framework extensions), ability to run
tests in parallel and accumulated test time logging reports.
So far the supported command-line args are:
- "--jobs=<num>" or "-j=<num>" to specify the number of parallel workers.
- "--seed=<hex>" to specify the RNG seed (random if not set).
- "--iterations=<num>" or "-i=<num>" to specify the number of iterations.
Compatibility Note:
To stay compatible with previous versions, the framework also supports
the two original positional arguments: the iterations count and the
RNG seed (in that order).
Calling `secp256k1_context_create` with `SECP256K1_FLAGS_TYPE_CONTEXT`
seems to be not strictly API-compliant, as the only allowed
(non-deprecated) value is `SECP256K1_CONTEXT_NONE`, even if the
former happens to map to the latter currently.
Fix this by not dynamically creating a context in the first place and
switch to using the static context, as it is sufficient for this
benchmark and presumably matches what the "no capabilities" comment
intended back then.
Relocate the clock time getter to tests_common.h to
make it easily reusable across test programs. This
will be useful for the upcoming unit test framework.
Context - why not placing it inside testutil.h?:
The bench program links against the production-compiled library,
not its own compiled version. Therefore, `gettime_i64()` cannot
be moved to testutil.h, because testutil.h calls
`secp256k1_pubkey_save()`, which exists only in the internal
secp256k1.c and not in the public API.
secp256k1_memclear has the side effect of undefining bytes for
valgrind checks. In some cases, we may want to zero bytes
but allow subsequent reads. So we split memclear into
memclear_explicit, which makes no guarantees about the content
of the buffer on return, and memzero_explicit, which guarantees
zero value on return.
Change the memset in partial_sign to use memzero_explicit.
325d65a8cf Rename and clear var containing k or -k (John Moffett)
Pull request description:
Follow-up to #1579. `buf` still holds the nonce or its negation, so ought to be cleared.
ACKs for top commit:
theStack:
Code review re-ACK 325d65a8cf
real-or-random:
utACK 325d65a8cf
Tree-SHA512: a2fe39d7c44cebc0abe712828d521c2a7aba1db2d9dc5fc811dcaf96f1e45494dba5d7f016b6d9200ab523641ff62083686dbc942284e0f548183aaf60d8bfa2
buf currently holds k or -k and isn't cleared, so clear it and rename to
nonce32 to clarify its sensitivity and match how it is named in the
corresponding ECDSA sign_inner.
5153cf1c91 tests: refactor tagged hash tests (josibake)
Pull request description:
Opened in response to https://github.com/bitcoin-core/secp256k1/pull/1698#discussion_r2269449070
---
We use tagged hashes in `modules/musig`, `modules/schnorrsig`, `modules/ellswift`, and the proposed `modules/silentpayments`. In looking for inspiration on how to add tagged hash midstate verification for https://github.com/bitcoin-core/secp256k1/pull/1698, it seemed like a good opportunity to DRY up the code across all of the modules.
I chose the convention used in the ellswift module as this seems the most idiomatic C. Since the tags are normally specified as strings in the BIPs, I also added a comment above each char array for convenience.
If its deemed too invasive to refactor the existing modules in this PR, I'm happy to drop the refactor commits for the ellswift and schnorrsig modules. All I need for https://github.com/bitcoin-core/secp256k1/pull/1698 is the first commit which moves the utility function out of the musig module to make it available to use in the silent payments module.
ACKs for top commit:
real-or-random:
utACK 5153cf1c91 assuming CI passes
theStack:
Code-review ACK 5153cf1c91
Tree-SHA512: 335ec3ee6a265e13cc379968f8fa1624534bef2389e4e21b85e6a9572ce1bd9dee4eabd2cb6d187ac974db3ab8246c2626d309ccfbee5744c30cf7560d1e261c
Move the sha256_tag_test_internal function out of the musig module
into tests.c. This makes it available to other modules wishing to verify tagged
hashes without needing to duplicate the function.
Change the function signature to expect a const unsigned char and update
the tagged hash tests to use static const unsigned char character
arrays (where necessary).
Add a comment for each tag. This is done as a convenience for checking
the strings against the protocol specifications, where the tags are
normally specified as strings.
Update tests in the ellswift and schnorrsig modules to use the
sha256_tag_test_internal helper function.
c82d84bb86 build: add CMake option for disabling symbol visibility attributes (Cory Fields)
ce7923874f build: Add SECP256K1_NO_API_VISIBILITY_ATTRIBUTES (Tim Ruffing)
e5297f6d79 build: Refactor visibility logic (Tim Ruffing)
Pull request description:
This is less invasive than #1695. The latter might be the right thing in a new library (and then we'd probably not support autotools in the first place), but any semantic change to this code has the potential to create news bug, or at least breakages for downstream users.
This is different from #1677 in that it does not set `hidden` explicitly. I agree with the comment in #1677 that setting `hidden` violates the principle of least surprise.
So this similar in spirit to #1674. So I wonder if this should also include
3eef7362c4. I'd say no, `fvisibility` should then set by the user. But can you, in CMake, set `CMAKE_C_VISIBILITY_PRESET` from a parent project?
ACKs for top commit:
hebasto:
ACK c82d84bb86, I have reviewed the code and it looks OK.
Tree-SHA512: dad36c32a108d813e8d4e1849260af43f79a9aa8fbfb9a42b07d737e0467924a511110df0a2c6761539a1587b617a1b11123610a3db9d4cdf2b985dfb3eb21da
37dd422b5c cmake: Emulate Libtool's behavior on FreeBSD (Hennadii Stepanov)
Pull request description:
Building the master branch @ f24b838bed on FreeBSD 14.3:
- with Autotools:
```
$ ./autogen.sh
$ ./configure --disable-static --prefix /tmp/AUTOTOOLS
$ gmake
$ gmake install
$ tree /tmp/AUTOTOOLS/lib
/tmp/AUTOTOOLS/lib
├── libsecp256k1.la
├── libsecp256k1.so -> libsecp256k1.so.5.0.1
├── libsecp256k1.so.5 -> libsecp256k1.so.5.0.1
├── libsecp256k1.so.5.0.1
└── pkgconfig
└── libsecp256k1.pc
2 directories, 5 files
```
- with CMake:
```
$ cmake -B build -DCMAKE_INSTALL_PREFIX=/tmp/CMAKE
$ cmake --build build
$ cmake --install build
$ tree /tmp/CMAKE/lib
/tmp/CMAKE/lib
├── cmake
│ └── libsecp256k1
│ ├── libsecp256k1-config-version.cmake
│ ├── libsecp256k1-config.cmake
│ ├── libsecp256k1-targets-relwithdebinfo.cmake
│ └── libsecp256k1-targets.cmake
├── libsecp256k1.so -> libsecp256k1.so.5
├── libsecp256k1.so.5
└── pkgconfig
└── libsecp256k1.pc
4 directories, 7 files
```
With this PR:
```
$ cmake -B build -DCMAKE_INSTALL_PREFIX=/tmp/CMAKE+PR
$ cmake --build build
$ cmake --install build
$ tree /tmp/CMAKE+PR/lib
/tmp/CMAKE+PR/lib
├── cmake
│ └── libsecp256k1
│ ├── libsecp256k1-config-version.cmake
│ ├── libsecp256k1-config.cmake
│ ├── libsecp256k1-targets-relwithdebinfo.cmake
│ └── libsecp256k1-targets.cmake
├── libsecp256k1.so -> libsecp256k1.so.5
├── libsecp256k1.so.5 -> libsecp256k1.so.5.0.1
├── libsecp256k1.so.5.0.1
└── pkgconfig
└── libsecp256k1.pc
4 directories, 8 files
```
From [FreeBSD Developers' Handbook](https://docs.freebsd.org/en/books/developers-handbook/policies/#policies-shlib):
> If you are adding shared library support to a port or other piece of software that does not have one, the version numbers should follow these rules. Generally, the resulting numbers will have nothing to do with the release version of the software.
>
> For ports:
>
> - Prefer using the number already selected by upstream
>
> - If upstream provides symbol versioning, ensure that we use their script
ACKs for top commit:
real-or-random:
utACK 37dd422b5c
Tree-SHA512: b603d7e293ae1fb15c2b3c05957dcc3cbe94294083ad1d8cb00b06b0e295597fa09719d32c18d628670952b6d00467f5bc884be9ab791baf59ec265e26032470
Parent projects (Bitcoin Core in this case) may wish to include secp256k1
in another static library (libbitcoinkernel) so that users are not forced
to bring their own static libsecp256k1.
Unfortunately, CMake lacks the machinery to link (combine) one static lib
into another.
To work around this, secp256k1_objs is exposed as an interface library which
parent projects can "link" into static libs..
Ubuntu 20.04 LTS has reached the end of standard support. There no
longer appear to be compelling reasons to maintain compatibility with
CMake 3.16.
The new suggested minimum, CMake 3.22, is shipped with Ubuntu 22.04 LTS,
which is supported until April 2027.
This change also introduces new CMake policies, from CMP0098 to CMP0128.
These function aliases have been described as DEPRECATED in the public
API docs already many years ago (see #701, commit 41fc7856), and in
addition explicit deprecation warnings are shown by the compiler at
least since the first official release 0.2.0 (see PR #1089, commit
fc94a2da), so it should be fine to just remove them by now.
Co-authored-by: Tim Ruffing <crypto@timruffing.de>
1823594761 Verify `compressed` argument in `secp256k1_eckey_pubkey_serialize` (Sebastian Falbesoner)
Pull request description:
Due to similarity to the public API function `secp256k1_ec_pubkey_serialize`, public API flags like `SECP256K1_EC_COMPRESSED` are sometimes mistakingly passed to `secp256k1_eckey_pubkey_serialize` in newly proposed code (this is currently the case for several modules in secp256k1-zkp, see https://github.com/BlockstreamResearch/secp256k1-zkp/pull/300), which is currently not detected. To avoid this in the future, a VERIFY_CHECK is added to check that the `compressed` argument is either 0 or 1.
ACKs for top commit:
real-or-random:
utACK 1823594761
stratospher:
ACK 1823594. Got tests failures when passing public API flags to `secp256k1_eckey_pubkey_serialize`.
Tree-SHA512: ca542afc87f33e436ba33dc55b285dfe3759007c446ef94503bc1044c7a0a7f7b2208ae82e2c9743fc5fa38cf386127f3fbfa02d2c242f28fab3041ee46f153b